gen.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. // Copyright 2017 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build ignore
  5. // +build ignore
  6. package main
  7. import (
  8. "flag"
  9. "log"
  10. "strconv"
  11. "strings"
  12. "golang.org/x/text/internal/cldrtree"
  13. "golang.org/x/text/internal/gen"
  14. "golang.org/x/text/language"
  15. "golang.org/x/text/unicode/cldr"
  16. )
  17. var (
  18. draft = flag.String("draft",
  19. "contributed",
  20. `Minimal draft requirements (approved, contributed, provisional, unconfirmed).`)
  21. )
  22. // TODO:
  23. // - Compile format patterns.
  24. // - Compress the large amount of redundancy in metazones.
  25. // - Split trees (with shared buckets) with data that is enough for default
  26. // formatting of Go Time values and tables that are needed for larger
  27. // variants.
  28. // - zone to metaZone mappings (in supplemental)
  29. // - Add more enum values and also some key maps for some of the elements.
  30. func main() {
  31. gen.Init()
  32. r := gen.OpenCLDRCoreZip()
  33. defer r.Close()
  34. d := &cldr.Decoder{}
  35. d.SetDirFilter("supplemental", "main")
  36. d.SetSectionFilter("dates")
  37. data, err := d.DecodeZip(r)
  38. if err != nil {
  39. log.Fatalf("DecodeZip: %v", err)
  40. }
  41. dates := cldrtree.New("dates")
  42. buildCLDRTree(data, dates)
  43. w := gen.NewCodeWriter()
  44. if err := dates.Gen(w); err != nil {
  45. log.Fatal(err)
  46. }
  47. gen.WriteCLDRVersion(w)
  48. w.WriteGoFile("tables.go", "date")
  49. w = gen.NewCodeWriter()
  50. if err := dates.GenTestData(w); err != nil {
  51. log.Fatal(err)
  52. }
  53. w.WriteGoFile("data_test.go", "date")
  54. }
  55. func buildCLDRTree(data *cldr.CLDR, dates *cldrtree.Builder) {
  56. context := cldrtree.Enum("context")
  57. widthMap := func(s string) string {
  58. // Align era with width values.
  59. if r, ok := map[string]string{
  60. "eraAbbr": "abbreviated",
  61. "eraNarrow": "narrow",
  62. "eraNames": "wide",
  63. }[s]; ok {
  64. s = r
  65. }
  66. // Prefix width to disambiguate with some overlapping length values.
  67. return "width" + strings.Title(s)
  68. }
  69. width := cldrtree.EnumFunc("width", widthMap, "abbreviated", "narrow", "wide")
  70. length := cldrtree.Enum("length", "short", "long")
  71. month := cldrtree.Enum("month", "leap7")
  72. relTime := cldrtree.EnumFunc("relTime", func(s string) string {
  73. x, err := strconv.ParseInt(s, 10, 8)
  74. if err != nil {
  75. log.Fatal("Invalid number:", err)
  76. }
  77. return []string{
  78. "before2",
  79. "before1",
  80. "current",
  81. "after1",
  82. "after2",
  83. "after3",
  84. }[x+2]
  85. })
  86. // Disambiguate keys like 'months' and 'sun'.
  87. cycleType := cldrtree.EnumFunc("cycleType", func(s string) string {
  88. return s + "CycleType"
  89. })
  90. field := cldrtree.EnumFunc("field", func(s string) string {
  91. return s + "Field"
  92. })
  93. timeType := cldrtree.EnumFunc("timeType", func(s string) string {
  94. if s == "" {
  95. return "genericTime"
  96. }
  97. return s + "Time"
  98. }, "generic")
  99. zoneType := []cldrtree.Option{cldrtree.SharedType(), timeType}
  100. metaZoneType := []cldrtree.Option{cldrtree.SharedType(), timeType}
  101. for _, lang := range data.Locales() {
  102. tag := language.Make(lang)
  103. ldml := data.RawLDML(lang)
  104. if ldml.Dates == nil {
  105. continue
  106. }
  107. x := dates.Locale(tag)
  108. if x := x.Index(ldml.Dates.Calendars); x != nil {
  109. for _, cal := range ldml.Dates.Calendars.Calendar {
  110. x := x.IndexFromType(cal)
  111. if x := x.Index(cal.Months); x != nil {
  112. for _, mc := range cal.Months.MonthContext {
  113. x := x.IndexFromType(mc, context)
  114. for _, mw := range mc.MonthWidth {
  115. x := x.IndexFromType(mw, width)
  116. for _, m := range mw.Month {
  117. x.SetValue(m.Yeartype+m.Type, m, month)
  118. }
  119. }
  120. }
  121. }
  122. if x := x.Index(cal.MonthPatterns); x != nil {
  123. for _, mc := range cal.MonthPatterns.MonthPatternContext {
  124. x := x.IndexFromType(mc, context)
  125. for _, mw := range mc.MonthPatternWidth {
  126. // Value is always leap, so no need to create a
  127. // subindex.
  128. for _, m := range mw.MonthPattern {
  129. x.SetValue(mw.Type, m, width)
  130. }
  131. }
  132. }
  133. }
  134. if x := x.Index(cal.CyclicNameSets); x != nil {
  135. for _, cns := range cal.CyclicNameSets.CyclicNameSet {
  136. x := x.IndexFromType(cns, cycleType)
  137. for _, cc := range cns.CyclicNameContext {
  138. x := x.IndexFromType(cc, context)
  139. for _, cw := range cc.CyclicNameWidth {
  140. x := x.IndexFromType(cw, width)
  141. for _, c := range cw.CyclicName {
  142. x.SetValue(c.Type, c)
  143. }
  144. }
  145. }
  146. }
  147. }
  148. if x := x.Index(cal.Days); x != nil {
  149. for _, dc := range cal.Days.DayContext {
  150. x := x.IndexFromType(dc, context)
  151. for _, dw := range dc.DayWidth {
  152. x := x.IndexFromType(dw, width)
  153. for _, d := range dw.Day {
  154. x.SetValue(d.Type, d)
  155. }
  156. }
  157. }
  158. }
  159. if x := x.Index(cal.Quarters); x != nil {
  160. for _, qc := range cal.Quarters.QuarterContext {
  161. x := x.IndexFromType(qc, context)
  162. for _, qw := range qc.QuarterWidth {
  163. x := x.IndexFromType(qw, width)
  164. for _, q := range qw.Quarter {
  165. x.SetValue(q.Type, q)
  166. }
  167. }
  168. }
  169. }
  170. if x := x.Index(cal.DayPeriods); x != nil {
  171. for _, dc := range cal.DayPeriods.DayPeriodContext {
  172. x := x.IndexFromType(dc, context)
  173. for _, dw := range dc.DayPeriodWidth {
  174. x := x.IndexFromType(dw, width)
  175. for _, d := range dw.DayPeriod {
  176. x.IndexFromType(d).SetValue(d.Alt, d)
  177. }
  178. }
  179. }
  180. }
  181. if x := x.Index(cal.Eras); x != nil {
  182. opts := []cldrtree.Option{width, cldrtree.SharedType()}
  183. if x := x.Index(cal.Eras.EraNames, opts...); x != nil {
  184. for _, e := range cal.Eras.EraNames.Era {
  185. x.IndexFromAlt(e).SetValue(e.Type, e)
  186. }
  187. }
  188. if x := x.Index(cal.Eras.EraAbbr, opts...); x != nil {
  189. for _, e := range cal.Eras.EraAbbr.Era {
  190. x.IndexFromAlt(e).SetValue(e.Type, e)
  191. }
  192. }
  193. if x := x.Index(cal.Eras.EraNarrow, opts...); x != nil {
  194. for _, e := range cal.Eras.EraNarrow.Era {
  195. x.IndexFromAlt(e).SetValue(e.Type, e)
  196. }
  197. }
  198. }
  199. if x := x.Index(cal.DateFormats); x != nil {
  200. for _, dfl := range cal.DateFormats.DateFormatLength {
  201. x := x.IndexFromType(dfl, length)
  202. for _, df := range dfl.DateFormat {
  203. for _, p := range df.Pattern {
  204. x.SetValue(p.Alt, p)
  205. }
  206. }
  207. }
  208. }
  209. if x := x.Index(cal.TimeFormats); x != nil {
  210. for _, tfl := range cal.TimeFormats.TimeFormatLength {
  211. x := x.IndexFromType(tfl, length)
  212. for _, tf := range tfl.TimeFormat {
  213. for _, p := range tf.Pattern {
  214. x.SetValue(p.Alt, p)
  215. }
  216. }
  217. }
  218. }
  219. if x := x.Index(cal.DateTimeFormats); x != nil {
  220. for _, dtfl := range cal.DateTimeFormats.DateTimeFormatLength {
  221. x := x.IndexFromType(dtfl, length)
  222. for _, dtf := range dtfl.DateTimeFormat {
  223. for _, p := range dtf.Pattern {
  224. x.SetValue(p.Alt, p)
  225. }
  226. }
  227. }
  228. // TODO:
  229. // - appendItems
  230. // - intervalFormats
  231. }
  232. }
  233. }
  234. // TODO: this is a lot of data and is probably relatively little used.
  235. // Store this somewhere else.
  236. if x := x.Index(ldml.Dates.Fields); x != nil {
  237. for _, f := range ldml.Dates.Fields.Field {
  238. x := x.IndexFromType(f, field)
  239. for _, d := range f.DisplayName {
  240. x.Index(d).SetValue(d.Alt, d)
  241. }
  242. for _, r := range f.Relative {
  243. x.Index(r).SetValue(r.Type, r, relTime)
  244. }
  245. for _, rt := range f.RelativeTime {
  246. x := x.Index(rt).IndexFromType(rt)
  247. for _, p := range rt.RelativeTimePattern {
  248. x.SetValue(p.Count, p)
  249. }
  250. }
  251. for _, rp := range f.RelativePeriod {
  252. x.Index(rp).SetValue(rp.Alt, rp)
  253. }
  254. }
  255. }
  256. if x := x.Index(ldml.Dates.TimeZoneNames); x != nil {
  257. format := x.IndexWithName("zoneFormat")
  258. for _, h := range ldml.Dates.TimeZoneNames.HourFormat {
  259. format.SetValue(h.Element(), h)
  260. }
  261. for _, g := range ldml.Dates.TimeZoneNames.GmtFormat {
  262. format.SetValue(g.Element(), g)
  263. }
  264. for _, g := range ldml.Dates.TimeZoneNames.GmtZeroFormat {
  265. format.SetValue(g.Element(), g)
  266. }
  267. for _, r := range ldml.Dates.TimeZoneNames.RegionFormat {
  268. x.Index(r).SetValue(r.Type, r, timeType)
  269. }
  270. set := func(x *cldrtree.Index, e []*cldr.Common, zone string) {
  271. for _, n := range e {
  272. x.Index(n, zoneType...).SetValue(zone, n)
  273. }
  274. }
  275. zoneWidth := []cldrtree.Option{length, cldrtree.SharedType()}
  276. zs := x.IndexWithName("zone")
  277. for _, z := range ldml.Dates.TimeZoneNames.Zone {
  278. for _, l := range z.Long {
  279. x := zs.Index(l, zoneWidth...)
  280. set(x, l.Generic, z.Type)
  281. set(x, l.Standard, z.Type)
  282. set(x, l.Daylight, z.Type)
  283. }
  284. for _, s := range z.Short {
  285. x := zs.Index(s, zoneWidth...)
  286. set(x, s.Generic, z.Type)
  287. set(x, s.Standard, z.Type)
  288. set(x, s.Daylight, z.Type)
  289. }
  290. }
  291. set = func(x *cldrtree.Index, e []*cldr.Common, zone string) {
  292. for _, n := range e {
  293. x.Index(n, metaZoneType...).SetValue(zone, n)
  294. }
  295. }
  296. zoneWidth = []cldrtree.Option{length, cldrtree.SharedType()}
  297. zs = x.IndexWithName("metaZone")
  298. for _, z := range ldml.Dates.TimeZoneNames.Metazone {
  299. for _, l := range z.Long {
  300. x := zs.Index(l, zoneWidth...)
  301. set(x, l.Generic, z.Type)
  302. set(x, l.Standard, z.Type)
  303. set(x, l.Daylight, z.Type)
  304. }
  305. for _, s := range z.Short {
  306. x := zs.Index(s, zoneWidth...)
  307. set(x, s.Generic, z.Type)
  308. set(x, s.Standard, z.Type)
  309. set(x, s.Daylight, z.Type)
  310. }
  311. }
  312. }
  313. }
  314. }