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 Ω = "ohm",
464
465
466
467
468
469 min = "minute",
470
471 [utfchar(0x2103)] = "celsius",
472 [utfchar(0x2109)] = "fahrenheit",
473}
474
475local short_operators = {
476 ["."] = "times",
477 ["*"] = "times",
478 ["/"] = "solidus",
479 [":"] = "outof",
480}
481
482local short_suffixes = {
483 ["1"] = "linear",
484 ["2"] = "square",
485 ["3"] = "cubic",
486 ["4"] = "quadratic",
487 ["+1"] = "linear",
488 ["+2"] = "square",
489 ["+3"] = "cubic",
490 ["+4"] = "quadratic",
491 ["-1"] = "inverse",
492 ["-1"] = "ilinear",
493 ["-2"] = "isquare",
494 ["-3"] = "icubic",
495 ["-4"] = "iquadratic",
496 ["^1"] = "linear",
497 ["^2"] = "square",
498 ["^3"] = "cubic",
499 ["^4"] = "quadratic",
500 ["^+1"] = "linear",
501 ["^+2"] = "square",
502 ["^+3"] = "cubic",
503 ["^+4"] = "quadratic",
504 ["^-1"] = "inverse",
505 ["^-1"] = "ilinear",
506 ["^-2"] = "isquare",
507 ["^-3"] = "icubic",
508 ["^-4"] = "iquadratic",
509}
510
511local symbol_units = {
512 Degrees = "degree",
513 Degree = "degree",
514
515 ["°"] = "degree",
516 ArcMinute = "arcminute",
517 ["′"] = "arcminute",
518 ArcSecond = "arcsecond",
519 ["″"] = "arcsecond",
520 Percent = "percent",
521 ["%"] = "percent",
522 Promille = "permille",
523 Permille = "permille",
524}
525
526local packaged_units = {
527 Micron = "micron",
528 mmHg = "millimetermercury",
529}
530
531
532
533local ctx_unitsPUS = context.unitsPUS
534local ctx_unitsPU = context.unitsPU
535local ctx_unitsPS = context.unitsPS
536local ctx_unitsP = context.unitsP
537local ctx_unitsUS = context.unitsUS
538local ctx_unitsU = context.unitsU
539local ctx_unitsS = context.unitsS
540local ctx_unitsO = context.unitsO
541local ctx_unitsN = context.unitsN
542local ctx_unitsC = context.unitsC
543local ctx_unitsQ = context.unitsQ
544local ctx_unitsRPM = context.unitsRPM
545local ctx_unitsRTO = context.unitsRTO
546local ctx_unitsRabout = context.unitsRabout
547local ctx_unitsNstart = context.unitsNstart
548local ctx_unitsNstop = context.unitsNstop
549local ctx_unitsNspace = context.unitsNspace
550local ctx_unitsPopen = context.unitsPopen
551local ctx_unitsPclose = context.unitsPclose
552
553local labels = languages.data.labels
554
555labels.prefixes = allocate {
556 yocto = { labels = { en = [[y]] } },
557 zepto = { labels = { en = [[z]] } },
558 atto = { labels = { en = [[a]] } },
559 femto = { labels = { en = [[f]] } },
560 pico = { labels = { en = [[p]] } },
561 nano = { labels = { en = [[n]] } },
562 micro = { labels = { en = [[\mu]] } },
563 milli = { labels = { en = [[m]] } },
564 centi = { labels = { en = [[c]] } },
565 deci = { labels = { en = [[d]] } },
566 deca = { labels = { en = [[da]] } },
567 hecto = { labels = { en = [[h]] } },
568 kilo = { labels = { en = [[k]] } },
569 mega = { labels = { en = [[M]] } },
570 giga = { labels = { en = [[G]] } },
571 tera = { labels = { en = [[T]] } },
572 peta = { labels = { en = [[P]] } },
573 exa = { labels = { en = [[E]] } },
574 zetta = { labels = { en = [[Z]] } },
575 yotta = { labels = { en = [[Y]] } },
576 kibi = { labels = { en = [[Ki]] } },
577 mebi = { labels = { en = [[Mi]] } },
578 gibi = { labels = { en = [[Gi]] } },
579 tebi = { labels = { en = [[Ti]] } },
580 pebi = { labels = { en = [[Pi]] } },
581 exbi = { labels = { en = [[Ei]] } },
582 zebi = { labels = { en = [[Zi]] } },
583 yobi = { labels = { en = [[Yi]] } },
584 micro = { labels = { en = [[µ]] } },
585 root = { labels = { en = [[√]] } },
586}
587
588labels.units = allocate {
589 meter = { labels = { en = [[m]] } },
590 gram = { labels = { en = [[g]] } },
591 second = { labels = { en = [[s]] } },
592 ampere = { labels = { en = [[A]] } },
593 kelvin = { labels = { en = [[K]] } },
594 mole = { labels = { en = [[mol]] } },
595 candela = { labels = { en = [[cd]] } },
596 mol = { labels = { en = [[mol]] } },
597 radian = { labels = { en = [[rad]] } },
598 steradian = { labels = { en = [[sr]] } },
599 hertz = { labels = { en = [[Hz]] } },
600 newton = { labels = { en = [[N]] } },
601 pascal = { labels = { en = [[Pa]] } },
602 joule = { labels = { en = [[J]] } },
603 watt = { labels = { en = [[W]] } },
604 coulomb = { labels = { en = [[C]] } },
605 volt = { labels = { en = [[V]] } },
606 farad = { labels = { en = [[F]] } },
607 ohm = { labels = { en = [[Ω]] } },
608 siemens = { labels = { en = [[S]] } },
609 weber = { labels = { en = [[Wb]] } },
610 mercury = { labels = { en = [[Hg]] } },
611 millimetermercury = { labels = { en = [[mmHg]] } },
612 tesla = { labels = { en = [[T]] } },
613 henry = { labels = { en = [[H]] } },
614 celsius = { labels = { en = [[\checkedtextcelsius]] } },
615 lumen = { labels = { en = [[lm]] } },
616 lux = { labels = { en = [[lx]] } },
617 becquerel = { labels = { en = [[Bq]] } },
618 gray = { labels = { en = [[Gy]] } },
619 sievert = { labels = { en = [[Sv]] } },
620 katal = { labels = { en = [[kat]] } },
621 minute = { labels = { en = [[min]] } },
622 hour = { labels = { en = [[h]] } },
623 day = { labels = { en = [[d]] } },
624 gon = { labels = { en = [[gon]] } },
625 grad = { labels = { en = [[grad]] } },
626 hectare = { labels = { en = [[ha]] } },
627 liter = { labels = { en = [[l]] } },
628 tonne = { labels = { en = [[t]] } },
629 electronvolt = { labels = { en = [[eV]] } },
630 dalton = { labels = { en = [[Da]] } },
631 atomicmassunit = { labels = { en = [[u]] } },
632 astronomicalunit = { labels = { en = [[au]] } },
633 bar = { labels = { en = [[bar]] } },
634 angstrom = { labels = { en = [[Å]] } },
635 nauticalmile = { labels = { en = [[M]] } },
636 barn = { labels = { en = [[b]] } },
637 knot = { labels = { en = [[kn]] } },
638 neper = { labels = { en = [[Np]] } },
639 bel = { labels = { en = [[B]] } },
640 erg = { labels = { en = [[erg]] } },
641 dyne = { labels = { en = [[dyn]] } },
642 poise = { labels = { en = [[P]] } },
643 stokes = { labels = { en = [[St]] } },
644 stilb = { labels = { en = [[sb]] } },
645 phot = { labels = { en = [[phot]] } },
646 gal = { labels = { en = [[gal]] } },
647 maxwell = { labels = { en = [[Mx]] } },
648 gauss = { labels = { en = [[G]] } },
649 oersted = { labels = { en = [[Oe]] } },
650 bit = { labels = { en = [[bit]] } },
651 byte = { labels = { en = [[B]] } },
652 baud = { labels = { en = [[Bd]] } },
653 erlang = { labels = { en = [[E]] } },
654 atmosphere = { labels = { en = [[atm]] } },
655 revolution = { labels = { en = [[rev]] } },
656 fahrenheit = { labels = { en = [[\checkedtextfahrenheit]] } },
657 foot = { labels = { en = [[ft]] } },
658 inch = { labels = { en = [[inch]] } },
659 calorie = { labels = { en = [[cal]] } },
660
661 degree = { labels = { en = [[°]]} },
662 arcminute = { labels = { en = [[\checkedtextprime]] } },
663 arcsecond = { labels = { en = [[\checkedtextdoubleprime]] } },
664 percent = { labels = { en = [[\percent]] } },
665 permille = { labels = { en = [[\promille]] } },
666
667 micron = { labels = { en = [[\textmu m]] } },
668}
669
670labels.operators = allocate {
671 times = { labels = { en = [[\unitsTIMES]] } },
672 solidus = { labels = { en = [[\unitsSOLIDUS]] } },
673 per = { labels = { en = [[\unitsSOLIDUS]] } },
674 outof = { labels = { en = [[\unitsOUTOF]] } },
675}
676
677labels.suffixes = allocate {
678 linear = { labels = { en = [[1]] } },
679 square = { labels = { en = [[2]] } },
680 cubic = { labels = { en = [[3]] } },
681 quadratic = { labels = { en = [[4]] } },
682 inverse = { labels = { en = [[\mathminus1]] } },
683 ilinear = { labels = { en = [[\mathminus1]] } },
684 isquare = { labels = { en = [[\mathminus2]] } },
685 icubic = { labels = { en = [[\mathminus3]] } },
686 iquadratic = { labels = { en = [[\mathminus4]] } },
687}
688
689local function dimpus(p,u,s)
690 if trace_units then
691 report_units("prefix %a, unit %a, suffix %a",p,u,s)
692 end
693 if p ~= "" then
694 if u ~= "" then
695 if s ~= "" then
696 ctx_unitsPUS(p,u,s)
697 else
698 ctx_unitsPU(p,u)
699 end
700 elseif s ~= "" then
701 ctx_unitsPS(p,s)
702 else
703 ctx_unitsP(p)
704 end
705 else
706 if u ~= "" then
707 if s ~= "" then
708 ctx_unitsUS(u,s)
709
710
711 else
712 ctx_unitsU(u)
713 end
714 elseif s ~= "" then
715 ctx_unitsS(s)
716 else
717 ctx_unitsP(p)
718 end
719 end
720end
721
722local function dimspu(s,p,u)
723 return dimpus(p,u,s)
724end
725
726local function dimop(o)
727 if trace_units then
728 report_units("operator %a",o)
729 end
730 if o then
731 ctx_unitsO(o)
732 end
733end
734
735local function dimsym(s)
736 if trace_units then
737 report_units("symbol %a",s)
738 end
739 s = symbol_units[s] or s
740 if s then
741 ctx_unitsC(s)
742 end
743end
744
745local function dimpre(p)
746 if trace_units then
747 report_units("prefix [%a",p)
748 end
749 p = packaged_units[p] or p
750 if p then
751 ctx_unitsU(p)
752 end
753end
754
755
756
757
758
759
760
761
762
763local function update_parsers()
764
765 local all_long_prefixes = { }
766 local all_long_units = { }
767 local all_long_operators = { }
768 local all_long_suffixes = { }
769 local all_symbol_units = { }
770 local all_packaged_units = { }
771
772 for k, v in next, long_prefixes do all_long_prefixes [k] = v all_long_prefixes [lower(k)] = v end
773 for k, v in next, long_units do all_long_units [k] = v all_long_units [lower(k)] = v end
774 for k, v in next, long_operators do all_long_operators[k] = v all_long_operators[lower(k)] = v end
775 for k, v in next, long_suffixes do all_long_suffixes [k] = v all_long_suffixes [lower(k)] = v end
776 for k, v in next, symbol_units do all_symbol_units [k] = v all_symbol_units [lower(k)] = v end
777 for k, v in next, packaged_units do all_packaged_units[k] = v all_packaged_units[lower(k)] = v end
778
779 local somespace = P(" ")^0/""
780
781 local p_long_prefix = appendlpeg(all_long_prefixes,nil,true)
782 local p_long_unit = appendlpeg(all_long_units,nil,true)
783 local p_long_operator = appendlpeg(all_long_operators,nil,true)
784 local p_long_suffix = appendlpeg(all_long_suffixes,nil,true)
785 local p_symbol = appendlpeg(all_symbol_units,nil,true)
786 local p_packaged = appendlpeg(all_packaged_units,nil,true)
787
788 local p_short_prefix = appendlpeg(short_prefixes)
789 local p_short_unit = appendlpeg(short_units)
790 local p_short_operator = appendlpeg(short_operators)
791 local p_short_suffix = appendlpeg(short_suffixes)
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809 local unitparser = P { "unit",
810
811 longprefix = Cs(V("somespace") * p_long_prefix),
812 shortprefix = Cs(V("somespace") * p_short_prefix),
813 longsuffix = Cs(V("somespace") * p_long_suffix),
814 shortsuffix = Cs(V("somespace") * p_short_suffix),
815 shortunit = Cs(V("somespace") * p_short_unit),
816 longunit = Cs(V("somespace") * p_long_unit),
817 longoperator = Cs(V("somespace") * p_long_operator),
818 shortoperator = Cs(V("somespace") * p_short_operator),
819 packaged = Cs(V("somespace") * p_packaged),
820
821 nothing = Cc(""),
822 somespace = somespace,
823 nospace = (1-somespace)^1,
824
825
826 qualifier = Cs(V("somespace") * (lparent/"") * (1-rparent)^1 * (rparent/"")),
827
828 somesymbol = V("somespace")
829 * (p_symbol/dimsym)
830 * V("somespace"),
831 somepackaged = V("somespace")
832 * (V("packaged") / dimpre)
833 * V("somespace"),
834
835
836
837
838 combination = V("longprefix") * V("longunit")
839 + V("nothing") * V("longunit")
840 + V("shortprefix") * V("shortunit")
841 + V("nothing") * V("shortunit")
842 + V("longprefix") * V("shortunit")
843 + V("shortprefix") * V("longunit"),
844
845
846
847
848
849
850
851
852
853
854
855
856 dimension = V("somespace")
857 * (
858 V("packaged") / dimpre
859 + (V("longsuffix") * V("combination")) / dimspu
860 + (V("combination") * (V("shortsuffix") + V("nothing"))) / dimpus
861 )
862 * (V("qualifier") / ctx_unitsQ)^-1
863 * V("somespace"),
864 operator = V("somespace")
865 * ((V("longoperator") + V("shortoperator")) / dimop)
866 * V("somespace"),
867 snippet = V("dimension")
868 + V("somesymbol"),
869 unit = ( V("snippet") * (V("operator") * V("snippet"))^0
870 + V("somepackaged")
871 )^1,
872 }
873
874
875
876 local letter = R("az","AZ")
877 local bound = #(1-letter)
878
879 local number = Cs( P("$") * (1-P("$"))^1 * P("$")
880 + P([[\m{]]) * (1-P("}"))^1 * P("}")
881 + (1-letter-P(" "))^1
882 ) / ctx_unitsN
883
884 local start = Cc(nil) / ctx_unitsNstart
885 local stop = Cc(nil) / ctx_unitsNstop
886 local space = P(" ") * Cc(nil) / ctx_unitsNspace
887 local open = P("(") * Cc(nil) / ctx_unitsPopen
888 local close = P(")") * Cc(nil) / ctx_unitsPclose
889
890 local range = somespace
891 * ( (P("±") + P("pm") * bound) / "" / ctx_unitsRPM
892 + (P("–") + P("to") * bound) / "" / ctx_unitsRTO )
893 * somespace
894
895 local about = (P("±") + P("pm") * bound) / "" / ctx_unitsRabout
896 * somespace
897
898
899
900 local function combine(parser)
901 return P { "start",
902 number = start * dleader * (parser + number) * stop,
903 anumber = space
904 * open
905 * V("about")^-1
906 * V("number")
907 * close,
908 rule = V("number")^-1
909 * (V("range") * V("number") + V("anumber"))^-1,
910 unit = unitparser,
911 about = about,
912 range = range,
913 space = space,
914 start = V("rule")
915 * V("unit")
916 * (V("space") * V("rule") * V("unit"))^0
917 + open
918 * V("number")
919 * (V("range") * V("number"))^-1
920 * close
921 * dtrailer^-1
922 * V("unit")
923 + V("number")
924 }
925 end
926
927 return combine(p_c_dparser), combine(c_p_dparser)
928end
929
930local p_c_parser = nil
931local c_p_parser = nil
932local dirty = true
933
934local function makeunit(str,reverse)
935 if dirty then
936 if trace_units then
937 report_units("initializing parser")
938 end
939 p_c_parser, c_p_parser = update_parsers()
940 dirty = false
941 end
942 local ok
943 if reverse then
944 ok = matchlpeg(p_c_parser,str)
945 else
946 ok = matchlpeg(c_p_parser,str)
947 end
948 if not ok then
949 report_units("unable to parse: %s",str)
950 context(str)
951 end
952end
953
954local function trigger(t,k,v)
955 rawset(t,k,v)
956 dirty = true
957end
958
959local t_units = {
960 prefixes = setmetatablenewindex(long_prefixes,trigger),
961 units = setmetatablenewindex(long_units,trigger),
962 operators = setmetatablenewindex(long_operators,trigger),
963 suffixes = setmetatablenewindex(long_suffixes,trigger),
964 symbols = setmetatablenewindex(symbol_units,trigger),
965 packaged = setmetatablenewindex(packaged_units,trigger),
966}
967
968local t_shortcuts = {
969 prefixes = setmetatablenewindex(short_prefixes,trigger),
970 units = setmetatablenewindex(short_units,trigger),
971 operators = setmetatablenewindex(short_operators,trigger),
972 suffixes = setmetatablenewindex(short_suffixes,trigger),
973}
974
975physics.units.tables = allocate {
976 units = t_units,
977 shortcuts = t_shortcuts,
978}
979
980local mapping = {
981 prefix = "prefixes",
982 unit = "units",
983 operator = "operators",
984 suffixe = "suffixes",
985 symbol = "symbols",
986 packaged = "packaged",
987}
988
989local function registerunit(category,list)
990 if not list or list == "" then
991 list = category
992 category = "unit"
993 end
994 local t = t_units[mapping[category]]
995 if t then
996 for k, v in next, utilities.parsers.settings_to_hash(list or "") do
997 t[k] = v
998 end
999 end
1000
1001end
1002
1003physics.units.registerunit = registerunit
1004
1005implement { name = "digits_normal", actions = makedigits, arguments = "string" }
1006implement { name = "digits_reverse", actions = makedigits, arguments = { "string", true } }
1007implement { name = "unit_normal", actions = makeunit, arguments = "string"}
1008implement { name = "unit_reverse", actions = makeunit, arguments = { "string", true } }
1009implement { name = "registerunit", actions = registerunit, arguments = "2 strings" }
1010
1011implement {
1012 name = "hyphenateddigits",
1013 public = true,
1014 protected = true,
1015 arguments = { "optional", "string" },
1016 actions = function(filler, digits)
1017 digits = gsub(digits,"(%d)","%1\\digitsbreak ")
1018 digits = gsub(digits,"\\-$",filler)
1019 context(digits)
1020 end
1021}
1022 |