1if not modules then modules = { } end modules ['phys-dim'] = {
2 version = 1.001,
3 comment = "companion to phys-dim.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42local rawset, next = rawset, next
43local V, P, S, R, C, Cc, Cs, matchlpeg = lpeg.V, lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.match
44local format, lower, gsub = string.format, string.lower, string.gsub
45local appendlpeg = lpeg.append
46local utfchartabletopattern = lpeg.utfchartabletopattern
47local mergetable, mergedtable, keys, loweredkeys = table.merge, table.merged, table.keys, table.loweredkeys
48local setmetatablenewindex = table.setmetatablenewindex
49local utfchar = utf.char
50
51physics = physics or { }
52physics.units = physics.units or { }
53
54local allocate = utilities.storage.allocate
55
56local context = context
57local commands = commands
58local implement = interfaces.implement
59
60local trace_units = false
61local report_units = logs.reporter("units")
62
63trackers.register("physics.units", function(v) trace_units = v end)
64
65
66
67local math_one = Cs((P("$") /"") * (1-P("$"))^1 * (P("$")/"")) / context.m
68local math_two = Cs((P("\\m {")/"") * (1-P("}"))^1 * (P("}")/"")) / context.m
69
70local digit = R("09")
71local plus = P("+")
72local minus = P("-")
73local plusminus = P("±")
74local sign = plus + minus
75local power = S("^e")
76local digitspace = S("~@_")
77local comma = P(",")
78local period = P(".")
79local semicolon = P(";")
80local colon = P(":")
81local signspace = P("/")
82local positive = P("++")
83local negative = P("--")
84local highspace = P("//")
85local padding = P("=")
86local space = P(" ")
87local lparent = P("(")
88local rparent = P(")")
89
90local lbrace = P("{")
91local rbrace = P("}")
92
93local digits = digit^1
94
95local powerdigits = plus * C(digits) / context.digitspowerplus
96 + minus * C(digits) / context.digitspowerminus
97 + C(digits) / context.digitspower
98
99local ddigitspace = digitspace / "" / context.digitsspace
100local ddigit = digits / context.digitsdigit
101local dsemicomma = semicolon / "" / context.digitsseparatorspace
102local dsemiperiod = colon / "" / context.digitsseparatorspace
103local dfinalcomma = comma / "" / context.digitsfinalcomma
104local dfinalperiod = period / "" / context.digitsfinalperiod
105local dintercomma = comma / "" / context.digitsintermediatecomma
106local dinterperiod = period / "" / context.digitsintermediateperiod
107local dskipcomma = comma / "" / context.digitsseparatorspace
108local dskipperiod = period / "" / context.digitsseparatorspace
109local dsignspace = signspace / "" / context.digitssignspace
110local dpositive = positive / "" / context.digitspositive
111local dnegative = negative / "" / context.digitsnegative
112local dhighspace = highspace / "" / context.digitshighspace
113local dsomesign = plus / "" / context.digitsplus
114 + minus / "" / context.digitsminus
115 + plusminus / "" / context.digitsplusminus
116local dpower = power / "" * ( powerdigits + lbrace * powerdigits * rbrace )
117
118local dpadding = padding / "" / context.digitszeropadding
119
120local dleader = (dpositive + dnegative + dhighspace + dsomesign + dsignspace)^0
121local dtrailer = dpower^0
122local dfinal = P(-1) + #P(1 - comma - period - semicolon - colon)
123local dnumber = (ddigitspace + ddigit)^1
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153local c_p = (ddigitspace^1 * dskipcomma)^0
154 * (ddigitspace^0 * ddigit * dintercomma)^0
155 * ddigitspace^0 * ddigit^0
156 * (
157 dfinalperiod * ddigit^1 * dpadding^1
158 + dfinalperiod * ddigit * (dintercomma * ddigit)^0
159 + dskipperiod * dpadding^1
160 + dsemiperiod * ddigit * (dintercomma * ddigit)^0
161 + dsemiperiod * dpadding^1
162 )^0
163 + ddigit
164
165local p_c = (ddigitspace^1 * dskipperiod)^0
166 * (ddigitspace^0 * ddigit * dinterperiod)^0
167 * ddigitspace^0 * ddigit^0
168 * (
169 dfinalcomma * ddigit^1 * dpadding^1
170 + dfinalcomma * ddigit * (dinterperiod * ddigit)^0
171 + dskipcomma * dpadding^1
172 + dsemicomma * ddigit * (dinterperiod * ddigit)^0
173 + dsemicomma * dpadding^1
174 )^0
175 + ddigit
176
177local p_c_dparser = math_one + math_two + dleader * p_c * dtrailer * dfinal
178local c_p_dparser = math_one + math_two + dleader * c_p * dtrailer * dfinal
179
180local function makedigits(str,reverse)
181 if reverse then
182 matchlpeg(p_c_dparser,str)
183 else
184 matchlpeg(c_p_dparser,str)
185 end
186end
187
188
189
190local long_prefixes = {
191
192
193
194 Yocto = "yocto",
195 Zepto = "zepto",
196 Atto = "atto",
197 Femto = "femto",
198 Pico = "pico",
199 Nano = "nano",
200 Micro = "micro",
201 Milli = "milli",
202 Centi = "centi",
203 Deci = "deci",
204
205 Deca = "deca",
206 Hecto = "hecto",
207 Kilo = "kilo",
208 Mega = "mega",
209 Giga = "giga",
210 Tera = "tera",
211 Peta = "peta",
212 Exa = "exa",
213 Zetta = "zetta",
214 Yotta = "yotta",
215
216
217
218 Kibi = "kibi",
219 Mebi = "mebi",
220 Gibi = "gibi",
221 Tebi = "tebi",
222 Pebi = "pebi",
223 Exbi = "exbi",
224
225
226
227 Zebi = "zebi",
228 Yobi = "yobi",
229
230 Micro = "micro",
231 Root = "root",
232}
233
234local long_units = {
235
236
237
238
239 Meter = "meter",
240 Gram = "gram",
241 Second = "second",
242 Ampere = "ampere",
243 Kelvin = "kelvin",
244 Mole = "mole",
245 Candela = "candela",
246
247
248
249 Mol = "mole",
250 Metre = "meter",
251
252
253
254 Radian = "radian",
255 Steradian = "steradian",
256 Hertz = "hertz",
257 Newton = "newton",
258 Pascal = "pascal",
259 Joule = "joule",
260 Watt = "watt",
261 Coulomb = "coulomb",
262 Volt = "volt",
263 Farad = "farad",
264 Ohm = "ohm",
265 Siemens = "siemens",
266 Weber = "weber",
267 Tesla = "tesla",
268 Henry = "henry",
269 Celsius = "celsius",
270 Lumen = "lumen",
271 Lux = "lux",
272 Becquerel = "becquerel",
273 Gray = "gray",
274 Sievert = "sievert",
275 Katal = "katal",
276
277
278
279 Minute = "minute",
280 Hour = "hour",
281 Day = "day",
282
283
284
285 Gon = "gon",
286 Grad = "grad",
287 Hectare = "hectare",
288 Liter = "liter",
289
290 Tonne = "tonne",
291
292
293
294 MetricTon = "tonne",
295 Litre = "liter",
296
297 ["Metric Ton"] = "tonne",
298
299
300
301 AtomicMassUnit = "atomicmassunit",
302 AstronomicalUnit = "astronomicalunit",
303 ElectronVolt = "electronvolt",
304 Dalton = "dalton",
305
306 ["Atomic Mass Unit"] = "atomicmassunit",
307 ["Astronomical Unit"] = "astronomicalunit",
308 ["Electron Volt"] = "electronvolt",
309
310
311
312 DegreesCelsius = "celsius",
313 DegreesFahrenheit = "fahrenheit",
314 DegreeCelsius = "celsius",
315 DegreeFahrenheit = "fahrenheit",
316
317 ["Degrees Celsius"] = "celsius",
318 ["Degrees Fahrenheit"] = "fahrenheit",
319 ["Degree Celsius"] = "celsius",
320 ["Degree Fahrenheit"] = "fahrenheit",
321
322
323
324
325
326
327
328
329
330
331
332 eV = "electronvolt",
333 AMU = "atomicmassunit",
334
335
336
337 Bar = "bar",
338 Hg = "mercury",
339
340 Angstrom = "angstrom",
341 NauticalMile = "nauticalmile",
342 Barn = "barn",
343 Knot = "knot",
344 Neper = "neper",
345 Bel = "bel",
346
347 ["Nautical Mile"] = "nauticalmile",
348
349
350
351 Erg = "erg",
352 Dyne = "dyne",
353 Poise = "poise",
354 Stokes = "stokes",
355 Stilb = "stilb",
356 Phot = "phot",
357 Gal = "gal",
358 Maxwell = "maxwell",
359 Gauss = "gauss",
360 Oersted = "oersted",
361
362
363
364
365
366 Bit = "bit",
367 Byte = "byte" ,
368 Baud = "baud",
369 Erlang = "erlang",
370
371
372
373 Atmosphere = "atmosphere",
374 Revolution = "revolution",
375
376
377
378 Atm = "atmosphere",
379 Rev = "revolution",
380
381
382
383 Fahrenheit = "fahrenheit",
384 Foot = "foot",
385 Inch = "inch",
386 Calorie = "calorie",
387
388
389
390 Cal = "calorie",
391
392}
393
394local long_operators = {
395
396 Times = "times",
397 Solidus = "solidus",
398 Per = "per",
399 OutOf = "outof",
400
401}
402
403local long_suffixes = {
404
405 Linear = "linear",
406 Square = "square",
407 Cubic = "cubic",
408 Quadratic = "quadratic",
409 Inverse = "inverse",
410 ILinear = "ilinear",
411 ISquare = "isquare",
412 ICubic = "icubic",
413 IQuadratic = "iquadratic",
414
415}
416
417local short_prefixes = {
418
419 y = "yocto",
420 z = "zetto",
421 a = "atto",
422 f = "femto",
423 p = "pico",
424 n = "nano",
425 u = "micro",
426 m = "milli",
427 c = "centi",
428 d = "deci",
429 da = "deca",
430 h = "hecto",
431 k = "kilo",
432 M = "mega",
433 G = "giga",
434 T = "tera",
435 P = "peta",
436 E = "exa",
437 Z = "zetta",
438 Y = "yotta",
439
440}
441
442local short_units = {
443
444 m = "meter",
445 Hz = "hertz",
446 hz = "hertz",
447 B = "bel",
448 b = "bel",
449 lx = "lux",
450
451 h = "hour",
452 s = "second",
453 g = "gram",
454 n = "newton",
455 v = "volt",
456 t = "tonne",
457 l = "liter",
458
459 W = "watt",
460
461 A = "ampere",
462
463 min = "minute",
464
465 [utfchar(0x2103)] = "celsius",
466 [utfchar(0x2109)] = "fahrenheit",
467}
468
469local short_operators = {
470 ["."] = "times",
471 ["*"] = "times",
472 ["/"] = "solidus",
473 [":"] = "outof",
474}
475
476local short_suffixes = {
477 ["1"] = "linear",
478 ["2"] = "square",
479 ["3"] = "cubic",
480 ["4"] = "quadratic",
481 ["+1"] = "linear",
482 ["+2"] = "square",
483 ["+3"] = "cubic",
484 ["+4"] = "quadratic",
485 ["-1"] = "inverse",
486 ["-1"] = "ilinear",
487 ["-2"] = "isquare",
488 ["-3"] = "icubic",
489 ["-4"] = "iquadratic",
490 ["^1"] = "linear",
491 ["^2"] = "square",
492 ["^3"] = "cubic",
493 ["^4"] = "quadratic",
494 ["^+1"] = "linear",
495 ["^+2"] = "square",
496 ["^+3"] = "cubic",
497 ["^+4"] = "quadratic",
498 ["^-1"] = "inverse",
499 ["^-1"] = "ilinear",
500 ["^-2"] = "isquare",
501 ["^-3"] = "icubic",
502 ["^-4"] = "iquadratic",
503}
504
505local symbol_units = {
506 Degrees = "degree",
507 Degree = "degree",
508
509 ["°"] = "degree",
510 ArcMinute = "arcminute",
511 ["′"] = "arcminute",
512 ArcSecond = "arcsecond",
513 ["″"] = "arcsecond",
514 Percent = "percent",
515 ["%"] = "percent",
516 Promille = "permille",
517 Permille = "permille",
518}
519
520local packaged_units = {
521 Micron = "micron",
522 mmHg = "millimetermercury",
523}
524
525
526
527local ctx_unitsPUS = context.unitsPUS
528local ctx_unitsPU = context.unitsPU
529local ctx_unitsPS = context.unitsPS
530local ctx_unitsP = context.unitsP
531local ctx_unitsUS = context.unitsUS
532local ctx_unitsU = context.unitsU
533local ctx_unitsS = context.unitsS
534local ctx_unitsO = context.unitsO
535local ctx_unitsN = context.unitsN
536local ctx_unitsC = context.unitsC
537local ctx_unitsQ = context.unitsQ
538local ctx_unitsRPM = context.unitsRPM
539local ctx_unitsRTO = context.unitsRTO
540local ctx_unitsRabout = context.unitsRabout
541local ctx_unitsNstart = context.unitsNstart
542local ctx_unitsNstop = context.unitsNstop
543local ctx_unitsNspace = context.unitsNspace
544local ctx_unitsPopen = context.unitsPopen
545local ctx_unitsPclose = context.unitsPclose
546
547local labels = languages.data.labels
548
549labels.prefixes = allocate {
550 yocto = { labels = { en = [[y]] } },
551 zepto = { labels = { en = [[z]] } },
552 atto = { labels = { en = [[a]] } },
553 femto = { labels = { en = [[f]] } },
554 pico = { labels = { en = [[p]] } },
555 nano = { labels = { en = [[n]] } },
556 micro = { labels = { en = [[\mu]] } },
557 milli = { labels = { en = [[m]] } },
558 centi = { labels = { en = [[c]] } },
559 deci = { labels = { en = [[d]] } },
560 deca = { labels = { en = [[da]] } },
561 hecto = { labels = { en = [[h]] } },
562 kilo = { labels = { en = [[k]] } },
563 mega = { labels = { en = [[M]] } },
564 giga = { labels = { en = [[G]] } },
565 tera = { labels = { en = [[T]] } },
566 peta = { labels = { en = [[P]] } },
567 exa = { labels = { en = [[E]] } },
568 zetta = { labels = { en = [[Z]] } },
569 yotta = { labels = { en = [[Y]] } },
570 kibi = { labels = { en = [[Ki]] } },
571 mebi = { labels = { en = [[Mi]] } },
572 gibi = { labels = { en = [[Gi]] } },
573 tebi = { labels = { en = [[Ti]] } },
574 pebi = { labels = { en = [[Pi]] } },
575 exbi = { labels = { en = [[Ei]] } },
576 zebi = { labels = { en = [[Zi]] } },
577 yobi = { labels = { en = [[Yi]] } },
578 micro = { labels = { en = [[µ]] } },
579 root = { labels = { en = [[√]] } },
580}
581
582labels.units = allocate {
583 meter = { labels = { en = [[m]] } },
584 gram = { labels = { en = [[g]] } },
585 second = { labels = { en = [[s]] } },
586 ampere = { labels = { en = [[A]] } },
587 kelvin = { labels = { en = [[K]] } },
588 mole = { labels = { en = [[mol]] } },
589 candela = { labels = { en = [[cd]] } },
590 mol = { labels = { en = [[mol]] } },
591 radian = { labels = { en = [[rad]] } },
592 steradian = { labels = { en = [[sr]] } },
593 hertz = { labels = { en = [[Hz]] } },
594 newton = { labels = { en = [[N]] } },
595 pascal = { labels = { en = [[Pa]] } },
596 joule = { labels = { en = [[J]] } },
597 watt = { labels = { en = [[W]] } },
598 coulomb = { labels = { en = [[C]] } },
599 volt = { labels = { en = [[V]] } },
600 farad = { labels = { en = [[F]] } },
601 ohm = { labels = { en = [[Ω]] } },
602 siemens = { labels = { en = [[S]] } },
603 weber = { labels = { en = [[Wb]] } },
604 mercury = { labels = { en = [[Hg]] } },
605 millimetermercury = { labels = { en = [[mmHg]] } },
606 tesla = { labels = { en = [[T]] } },
607 henry = { labels = { en = [[H]] } },
608 celsius = { labels = { en = [[\checkedtextcelsius]] } },
609 lumen = { labels = { en = [[lm]] } },
610 lux = { labels = { en = [[lx]] } },
611 becquerel = { labels = { en = [[Bq]] } },
612 gray = { labels = { en = [[Gy]] } },
613 sievert = { labels = { en = [[Sv]] } },
614 katal = { labels = { en = [[kat]] } },
615 minute = { labels = { en = [[min]] } },
616 hour = { labels = { en = [[h]] } },
617 day = { labels = { en = [[d]] } },
618 gon = { labels = { en = [[gon]] } },
619 grad = { labels = { en = [[grad]] } },
620 hectare = { labels = { en = [[ha]] } },
621 liter = { labels = { en = [[l]] } },
622 tonne = { labels = { en = [[t]] } },
623 electronvolt = { labels = { en = [[eV]] } },
624 dalton = { labels = { en = [[Da]] } },
625 atomicmassunit = { labels = { en = [[u]] } },
626 astronomicalunit = { labels = { en = [[au]] } },
627 bar = { labels = { en = [[bar]] } },
628 angstrom = { labels = { en = [[Å]] } },
629 nauticalmile = { labels = { en = [[M]] } },
630 barn = { labels = { en = [[b]] } },
631 knot = { labels = { en = [[kn]] } },
632 neper = { labels = { en = [[Np]] } },
633 bel = { labels = { en = [[B]] } },
634 erg = { labels = { en = [[erg]] } },
635 dyne = { labels = { en = [[dyn]] } },
636 poise = { labels = { en = [[P]] } },
637 stokes = { labels = { en = [[St]] } },
638 stilb = { labels = { en = [[sb]] } },
639 phot = { labels = { en = [[phot]] } },
640 gal = { labels = { en = [[gal]] } },
641 maxwell = { labels = { en = [[Mx]] } },
642 gauss = { labels = { en = [[G]] } },
643 oersted = { labels = { en = [[Oe]] } },
644 bit = { labels = { en = [[bit]] } },
645 byte = { labels = { en = [[B]] } },
646 baud = { labels = { en = [[Bd]] } },
647 erlang = { labels = { en = [[E]] } },
648 atmosphere = { labels = { en = [[atm]] } },
649 revolution = { labels = { en = [[rev]] } },
650 fahrenheit = { labels = { en = [[\checkedtextfahrenheit]] } },
651 foot = { labels = { en = [[ft]] } },
652 inch = { labels = { en = [[inch]] } },
653 calorie = { labels = { en = [[cal]] } },
654
655 degree = { labels = { en = [[°]]} },
656 arcminute = { labels = { en = [[\checkedtextprime]] } },
657 arcsecond = { labels = { en = [[\checkedtextdoubleprime]] } },
658 percent = { labels = { en = [[\percent]] } },
659 permille = { labels = { en = [[\promille]] } },
660
661 micron = { labels = { en = [[\textmu m]] } },
662}
663
664labels.operators = allocate {
665 times = { labels = { en = [[\unitsTIMES]] } },
666 solidus = { labels = { en = [[\unitsSOLIDUS]] } },
667 per = { labels = { en = [[\unitsSOLIDUS]] } },
668 outof = { labels = { en = [[\unitsOUTOF]] } },
669}
670
671labels.suffixes = allocate {
672 linear = { labels = { en = [[1]] } },
673 square = { labels = { en = [[2]] } },
674 cubic = { labels = { en = [[3]] } },
675 quadratic = { labels = { en = [[4]] } },
676 inverse = { labels = { en = [[\mathminus1]] } },
677 ilinear = { labels = { en = [[\mathminus1]] } },
678 isquare = { labels = { en = [[\mathminus2]] } },
679 icubic = { labels = { en = [[\mathminus3]] } },
680 iquadratic = { labels = { en = [[\mathminus4]] } },
681}
682
683local function dimpus(p,u,s)
684 if trace_units then
685 report_units("prefix %a, unit %a, suffix %a",p,u,s)
686 end
687 if p ~= "" then
688 if u ~= "" then
689 if s ~= "" then
690 ctx_unitsPUS(p,u,s)
691 else
692 ctx_unitsPU(p,u)
693 end
694 elseif s ~= "" then
695 ctx_unitsPS(p,s)
696 else
697 ctx_unitsP(p)
698 end
699 else
700 if u ~= "" then
701 if s ~= "" then
702 ctx_unitsUS(u,s)
703
704
705 else
706 ctx_unitsU(u)
707 end
708 elseif s ~= "" then
709 ctx_unitsS(s)
710 else
711 ctx_unitsP(p)
712 end
713 end
714end
715
716local function dimspu(s,p,u)
717 return dimpus(p,u,s)
718end
719
720local function dimop(o)
721 if trace_units then
722 report_units("operator %a",o)
723 end
724 if o then
725 ctx_unitsO(o)
726 end
727end
728
729local function dimsym(s)
730 if trace_units then
731 report_units("symbol %a",s)
732 end
733 s = symbol_units[s] or s
734 if s then
735 ctx_unitsC(s)
736 end
737end
738
739local function dimpre(p)
740 if trace_units then
741 report_units("prefix [%a",p)
742 end
743 p = packaged_units[p] or p
744 if p then
745 ctx_unitsU(p)
746 end
747end
748
749
750
751
752
753
754
755
756
757local function update_parsers()
758
759 local all_long_prefixes = { }
760 local all_long_units = { }
761 local all_long_operators = { }
762 local all_long_suffixes = { }
763 local all_symbol_units = { }
764 local all_packaged_units = { }
765
766 for k, v in next, long_prefixes do all_long_prefixes [k] = v all_long_prefixes [lower(k)] = v end
767 for k, v in next, long_units do all_long_units [k] = v all_long_units [lower(k)] = v end
768 for k, v in next, long_operators do all_long_operators[k] = v all_long_operators[lower(k)] = v end
769 for k, v in next, long_suffixes do all_long_suffixes [k] = v all_long_suffixes [lower(k)] = v end
770 for k, v in next, symbol_units do all_symbol_units [k] = v all_symbol_units [lower(k)] = v end
771 for k, v in next, packaged_units do all_packaged_units[k] = v all_packaged_units[lower(k)] = v end
772
773 local somespace = P(" ")^0/""
774
775 local p_long_prefix = appendlpeg(all_long_prefixes,nil,true)
776 local p_long_unit = appendlpeg(all_long_units,nil,true)
777 local p_long_operator = appendlpeg(all_long_operators,nil,true)
778 local p_long_suffix = appendlpeg(all_long_suffixes,nil,true)
779 local p_symbol = appendlpeg(all_symbol_units,nil,true)
780 local p_packaged = appendlpeg(all_packaged_units,nil,true)
781
782 local p_short_prefix = appendlpeg(short_prefixes)
783 local p_short_unit = appendlpeg(short_units)
784 local p_short_operator = appendlpeg(short_operators)
785 local p_short_suffix = appendlpeg(short_suffixes)
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803 local unitparser = P { "unit",
804
805 longprefix = Cs(V("somespace") * p_long_prefix),
806 shortprefix = Cs(V("somespace") * p_short_prefix),
807 longsuffix = Cs(V("somespace") * p_long_suffix),
808 shortsuffix = Cs(V("somespace") * p_short_suffix),
809 shortunit = Cs(V("somespace") * p_short_unit),
810 longunit = Cs(V("somespace") * p_long_unit),
811 longoperator = Cs(V("somespace") * p_long_operator),
812 shortoperator = Cs(V("somespace") * p_short_operator),
813 packaged = Cs(V("somespace") * p_packaged),
814
815 nothing = Cc(""),
816 somespace = somespace,
817 nospace = (1-somespace)^1,
818
819
820 qualifier = Cs(V("somespace") * (lparent/"") * (1-rparent)^1 * (rparent/"")),
821
822 somesymbol = V("somespace")
823 * (p_symbol/dimsym)
824 * V("somespace"),
825 somepackaged = V("somespace")
826 * (V("packaged") / dimpre)
827 * V("somespace"),
828
829
830
831
832 combination = V("longprefix") * V("longunit")
833 + V("nothing") * V("longunit")
834 + V("shortprefix") * V("shortunit")
835 + V("nothing") * V("shortunit")
836 + V("longprefix") * V("shortunit")
837 + V("shortprefix") * V("longunit"),
838
839
840
841
842
843
844
845
846
847
848
849
850 dimension = V("somespace")
851 * (
852 V("packaged") / dimpre
853 + (V("longsuffix") * V("combination")) / dimspu
854 + (V("combination") * (V("shortsuffix") + V("nothing"))) / dimpus
855 )
856 * (V("qualifier") / ctx_unitsQ)^-1
857 * V("somespace"),
858 operator = V("somespace")
859 * ((V("longoperator") + V("shortoperator")) / dimop)
860 * V("somespace"),
861 snippet = V("dimension")
862 + V("somesymbol"),
863 unit = ( V("snippet") * (V("operator") * V("snippet"))^0
864 + V("somepackaged")
865 )^1,
866 }
867
868
869
870 local letter = R("az","AZ")
871 local bound = #(1-letter)
872
873 local number = Cs( P("$") * (1-P("$"))^1 * P("$")
874 + P([[\m{]]) * (1-P("}"))^1 * P("}")
875 + (1-letter-P(" "))^1
876 ) / ctx_unitsN
877
878 local start = Cc(nil) / ctx_unitsNstart
879 local stop = Cc(nil) / ctx_unitsNstop
880 local space = P(" ") * Cc(nil) / ctx_unitsNspace
881 local open = P("(") * Cc(nil) / ctx_unitsPopen
882 local close = P(")") * Cc(nil) / ctx_unitsPclose
883
884 local range = somespace
885 * ( (P("±") + P("pm") * bound) / "" / ctx_unitsRPM
886 + (P("–") + P("to") * bound) / "" / ctx_unitsRTO )
887 * somespace
888
889 local about = (P("±") + P("pm") * bound) / "" / ctx_unitsRabout
890 * somespace
891
892
893
894 local function combine(parser)
895 return P { "start",
896 number = start * dleader * (parser + number) * stop,
897 anumber = space
898 * open
899 * V("about")^-1
900 * V("number")
901 * close,
902 rule = V("number")^-1
903 * (V("range") * V("number") + V("anumber"))^-1,
904 unit = unitparser,
905 about = about,
906 range = range,
907 space = space,
908 start = V("rule")
909 * V("unit")
910 * (V("space") * V("rule") * V("unit"))^0
911 + open
912 * V("number")
913 * (V("range") * V("number"))^-1
914 * close
915 * dtrailer^-1
916 * V("unit")
917 + V("number")
918 }
919 end
920
921 return combine(p_c_dparser), combine(c_p_dparser)
922end
923
924local p_c_parser = nil
925local c_p_parser = nil
926local dirty = true
927
928local function makeunit(str,reverse)
929 if dirty then
930 if trace_units then
931 report_units("initializing parser")
932 end
933 p_c_parser, c_p_parser = update_parsers()
934 dirty = false
935 end
936 local ok
937 if reverse then
938 ok = matchlpeg(p_c_parser,str)
939 else
940 ok = matchlpeg(c_p_parser,str)
941 end
942 if not ok then
943 report_units("unable to parse: %s",str)
944 context(str)
945 end
946end
947
948local function trigger(t,k,v)
949 rawset(t,k,v)
950 dirty = true
951end
952
953local t_units = {
954 prefixes = setmetatablenewindex(long_prefixes,trigger),
955 units = setmetatablenewindex(long_units,trigger),
956 operators = setmetatablenewindex(long_operators,trigger),
957 suffixes = setmetatablenewindex(long_suffixes,trigger),
958 symbols = setmetatablenewindex(symbol_units,trigger),
959 packaged = setmetatablenewindex(packaged_units,trigger),
960}
961
962local t_shortcuts = {
963 prefixes = setmetatablenewindex(short_prefixes,trigger),
964 units = setmetatablenewindex(short_units,trigger),
965 operators = setmetatablenewindex(short_operators,trigger),
966 suffixes = setmetatablenewindex(short_suffixes,trigger),
967}
968
969physics.units.tables = allocate {
970 units = t_units,
971 shortcuts = t_shortcuts,
972}
973
974local mapping = {
975 prefix = "prefixes",
976 unit = "units",
977 operator = "operators",
978 suffixe = "suffixes",
979 symbol = "symbols",
980 packaged = "packaged",
981}
982
983local function registerunit(category,list)
984 if not list or list == "" then
985 list = category
986 category = "unit"
987 end
988 local t = t_units[mapping[category]]
989 if t then
990 for k, v in next, utilities.parsers.settings_to_hash(list or "") do
991 t[k] = v
992 end
993 end
994
995end
996
997physics.units.registerunit = registerunit
998
999implement { name = "digits_normal", actions = makedigits, arguments = "string" }
1000implement { name = "digits_reverse", actions = makedigits, arguments = { "string", true } }
1001implement { name = "unit_normal", actions = makeunit, arguments = "string"}
1002implement { name = "unit_reverse", actions = makeunit, arguments = { "string", true } }
1003implement { name = "registerunit", actions = registerunit, arguments = "2 strings" }
1004
1005implement {
1006 name = "hyphenateddigits",
1007 public = true,
1008 protected = true,
1009 arguments = { "optional", "string" },
1010 actions = function(filler, digits)
1011 digits = gsub(digits,"(%d)","%1\\digitsbreak")
1012 digits = gsub(digits,"\\-$",filler)
1013 context(digits)
1014 end
1015}
1016 |