s-system-syntax.lmt /size: 90 Kb    last modification: 2025-02-21 11:03
1local setmetatableindex, sortedhash, concat = table.setmetatableindex, table.sortedhash, table.concat
2local sub, gsub, count = string.sub, string.gsub, string.count
3local lpegmatch = lpeg.match
4
5local context = context
6
7local moduledata   = moduledata        or { }
8moduledata.engine  = moduledata.engine or { }
9moduledata.mplib   = moduledata.mplib  or { }
10moduledata.pdfe    = moduledata.pdfe   or { }
11moduledata.node    = moduledata.node   or { }
12
13local primitives   = token.getprimitives()
14local commandnames = tokens.commands
15local origins      = tex.getprimitiveorigins()
16local commandhash  = { }
17local keywords     = setmetatableindex("number")
18
19for i=1,#primitives do
20    local p = primitives[i]
21    commandhash[p[3]] = p
22end
23
24local result = setmetatableindex(function(t,k)
25    local v = setmetatableindex(function(t,k)
26        local v = ""
27        t[k] = v
28        return v
29    end)
30    t[k]= v
31    return v
32end)
33
34local function TODO(t,k)
35    local v = "TODO"
36    t[k] = v
37    return v
38end
39
40local function newsyntax(t)
41    return setmetatableindex(t or { }, TODO)
42end
43
44local function newresult(t)
45    return t or { }
46end
47
48local category = setmetatableindex(function(t,k)
49    local v = "unset" -- might go
50    t[k]= v
51    return v
52end)
53
54local syntax = setmetatableindex(function(t,k)
55    local v = newsyntax()
56    t[k]= v
57    return v
58end)
59
60local function equals(...)
61    local t = { ... }
62    table.insert(t,#t,"[=]")
63    return concat(t," ")
64end
65
66local function sequence(...)
67    return concat({ ... }," ")
68end
69
70local function optional(s)
71    return "[" .. s .. "]"
72end
73
74local function choice(t,...)
75    return "( " .. concat(type(t) == "table" and t or { t, ... }," | ") .. ")"
76end
77
78local function repeated(...)
79    return "n * ( " .. concat({ ... }," ") .. ")"
80end
81
82local function keyword(s)
83    keywords[s] = keywords[s] + 1
84    return s
85end
86
87local s_dimension     = "dimension"
88local s_integer       = "integer"
89local s_cardinal      = "cardinal"
90local s_index         = "index"
91local s_float         = "float"
92local s_glue          = "glue"
93local s_muglue        = "muglue"
94local s_tokens        = "{tokens}"
95local s_token         = "token"
96local s_toks          = "toks"
97local s_mathstyle     = "mathstyle"
98local s_mathchar      = "mathchar"
99local s_quantity      = "quantity"
100local s_delimiter     = "delimiter"
101local s_nucleus       = "nucleus"
102local s_box           = "box"
103local s_cs            = "cs"
104local s_mathparameter = "mathparameter"
105local s_filler        = "fi[n*l]"
106local s_fontchar      = s_integer
107local s_character     = "character"
108local s_font          = choice("font",s_integer)
109local s_mathtokens    = choice("mathatom",s_tokens)
110local s_filename      = choice("{filename}","filename")
111local s_boxreference  = choice(s_index,s_box)
112local s_number        = choice(s_integer,s_float)
113local s_family        = "family"
114local s_rule          = "rule"
115local s_glyph         = "glyph"
116local s_todo          = "TODO"
117local s_specification = [==[tokens\relax]==]
118local s_expression    = [==[tokens\relax]==]
119local s_conditional   = [==[\if...]==]
120local s_tokens_or     = [==[tokens\or]==]
121local s_tokens_relax  = [==[tokens\relax]==]
122local s_tokens_endcs  = [==[tokens\endcsname]==]
123local s_tokens_endlc  = [==[tokens\endlocalcontrol]==]
124local s_parameter_or  = [==[parameter\or]==]
125
126local c_tokens        = "tokens"
127
128local r_dimension     = { "", s_dimension }
129local r_glue          = { "", s_glue }
130local r_integer       = { "", s_integer }
131local r_muglue        = { "", s_muglue }
132local r_toks          = { "", s_toks }
133local r_tokens        = { "", c_tokens }
134
135local f_see           = string.formatters["see \\type{\\%s}"]
136
137local function setdefaultresult(syntax, value)
138    local default = { }
139    for k in next, syntax do
140        default[k] = value
141    end
142    return default
143end
144
145local function setsyntaxfromresult(t)
146    local s = newsyntax()
147    for k, v in next, t do
148        s[k] = v and concat(v," [=] ") or false
149    end
150    return s
151end
152
153local compares = {
154    [0x003C] = "less",
155    [0x003D] = "equal",
156    [0x003E] = "greater",
157    [0x0021] = "negate next",
158    [0x2208] = "element",
159    [0x2209] = "not element",
160    [0x2260] = "not equal",
161    [0x2264] = "not greater",
162    [0x2265] = "not less",
163    [0x2270] = "not greater",
164    [0x2271] = "not less",
165}
166
167moduledata.engine.compares = compares
168
169local s_comparison = table.sortedkeys(compares) for i=1,#s_comparison do s_comparison[i] = utf.char(s_comparison[i]) end
170
171local o_equal      = optional("=")
172local s_comparison = choice(s_comparison)
173local o_preamble   = optional("preamble")
174
175-- start of syntax specification
176
177syntax.accent = newsyntax {
178    accent = sequence(
179        optional(sequence(keyword("xoffset"),s_dimension)),
180        optional(sequence(keyword("yoffset"),s_dimension)),
181        s_integer,
182        s_character
183    )
184}
185
186syntax.alignmenttab = newsyntax {
187    aligntab = false,
188}
189
190syntax.aftersomething = newsyntax {
191    afterassigned   = s_tokens,
192    afterassignment = s_token,
193    aftergroup      = s_token,
194    aftergrouped    = s_tokens,
195    atendofgroup    = s_token,
196    atendofgrouped  = s_tokens,
197    atendoffile     = s_token,
198    atendoffiled    = sequence(optional(keyword("reverse")),s_tokens),
199}
200
201result.association = newresult {
202    associateunit = { s_cs, s_integer }
203}
204
205syntax.association = setsyntaxfromresult(result.association)
206
207
208syntax.begingroup = newsyntax {
209    begingroup       = false,
210    beginmathgroup   = false,
211    beginsimplegroup = false,
212}
213
214syntax.arithmic = newsyntax {
215    advance    = sequence(s_quantity,optional(keyword("by")),s_quantity),
216    divide     = sequence(s_quantity,optional(keyword("by")),s_quantity),
217    multiply   = sequence(s_quantity,optional(keyword("by")),s_quantity),
218    advanceby  = sequence(s_quantity,s_quantity),
219    divideby   = sequence(s_quantity,s_quantity),
220    multiplyby = sequence(s_quantity,s_quantity),
221    edivide    = sequence(s_quantity,s_quantity),
222    edivideby  = sequence(s_quantity,s_quantity),
223    rdivide    = sequence(s_quantity,s_quantity),
224    rdivideby  = sequence(s_quantity,s_quantity),
225}
226
227syntax.beginlocal = newsyntax {
228    beginlocalcontrol      = false,
229    localcontrol           = s_tokens_endlc,
230    localcontrolled        = s_tokens,
231    localcontrolledloop    = sequence(s_integer,s_integer,s_integer,s_tokens),
232    expandedloop           = sequence(s_integer,s_integer,s_integer,s_tokens),
233    unexpandedloop         = sequence(s_integer,s_integer,s_integer,s_tokens),
234    localcontrolledrepeat  = sequence(s_integer,s_tokens),
235    expandedrepeat         = sequence(s_integer,s_tokens),
236    unexpandedrepeat       = sequence(s_integer,s_tokens),
237    localcontrolledendless = s_tokens,
238    expandedendless        = s_tokens,
239    unexpandedendless      = s_tokens,
240}
241
242syntax.beginparagraph = newsyntax {
243    indent       = false,
244    noindent     = false,
245    parattribute = sequence(s_integer,o_equal,s_integer),
246    paroptions   = sequence(o_equal,s_integer),
247    quitvmode    = false,
248    snapshotpar  = s_cardinal,
249    undent       = false,
250    wrapuppar    = sequence(optional(keyword("reverse")),s_tokens),
251}
252
253result.beginparagraph = newresult {
254    indent       = false,
255    noindent     = false,
256    parattribute = false,
257    quitvmode    = false,
258    snapshotpar  = r_integer,
259    undent       = false,
260    wrapuppar    = false,
261}
262
263syntax.boundary = newsyntax {
264    balanceboundary    = sequence(o_equal,s_integer,s_integer),
265    boundary           = sequence(o_equal,s_integer),
266    noboundary         = false,
267    mathboundary       = sequence(o_equal,s_integer,optional(s_integer)),
268    optionalboundary   = sequence(o_equal,s_integer), -- linebreak optionals
269    pageboundary       = sequence(o_equal,s_integer),
270    protrusionboundary = sequence(o_equal,s_integer),
271    wordboundary       = false,
272    luaboundary        = sequence(o_equal,s_integer,s_integer),
273}
274
275syntax.caseshift = newsyntax {
276    lowercase = s_tokens,
277    uppercase = s_tokens,
278}
279
280syntax.catcodetable = newsyntax {
281    initcatcodetable = s_integer,
282    restorecatcodetable = s_integer,
283    savecatcodetable = s_integer,
284}
285
286syntax.charnumber = newsyntax {
287    char  = s_integer,
288    glyph = sequence(
289        optional(sequence(keyword("xoffset"),s_dimension)),
290        optional(sequence(keyword("yoffset"),s_dimension)),
291        optional(sequence(keyword("scale"),s_integer)),
292        optional(sequence(keyword("xscale"),s_integer)),
293        optional(sequence(keyword("yscale"),s_integer)),
294        optional(sequence(keyword("left"),s_dimension)),
295        optional(sequence(keyword("right"),s_dimension)),
296        optional(sequence(keyword("raise"),s_dimension)),
297        optional(sequence(keyword("options"),s_integer)),
298        optional(sequence(keyword("font"),s_integer)),
299        optional(sequence(keyword("id"),s_integer)),
300        s_integer
301    ),
302}
303
304syntax.combinetoks = newsyntax {
305    etoks    = sequence(s_toks,s_tokens),
306    etoksapp = sequence(s_toks,s_tokens),
307    etokspre = sequence(s_toks,s_tokens),
308    gtoksapp = sequence(s_toks,s_tokens),
309    gtokspre = sequence(s_toks,s_tokens),
310    toksapp  = sequence(s_toks,s_tokens),
311    tokspre  = sequence(s_toks,s_tokens),
312    xtoks    = sequence(s_toks,s_tokens),
313    xtoksapp = sequence(s_toks,s_tokens),
314    xtokspre = sequence(s_toks,s_tokens),
315}
316
317result.convert = newresult {
318    tocharacter       = { s_integer, c_tokens },
319    csactive          = { s_token, c_tokens },
320    csnamestring      = { "", c_tokens },
321    csstring          = { s_token, c_tokens },
322    detokened         = { choice(s_cs,s_tokens,s_toks,s_tok), c_tokens },
323    detokenized       = { s_tokens, c_tokens },
324    directlua         = { s_tokens, c_tokens },
325    expanded          = { s_tokens, c_tokens },
326    fontname          = { s_font, c_tokens },
327    fontspecifiedname = { s_font, c_tokens },
328    fontidentifier    = { s_font, c_tokens },
329    formatname        = { "", c_tokens },
330    jobname           = { "", c_tokens },
331    luabytecode       = { s_integer, c_tokens },
332    luaescapestring   = { s_tokens, c_tokens },
333    luafunction       = { s_integer, c_tokens },
334    luatexbanner      = { "", c_tokens },
335    meaning           = { s_token, c_tokens },
336    meaningasis       = { s_token, c_tokens },
337    meaningful        = { s_token, c_tokens },
338    meaningfull       = { s_token, c_tokens },
339    meaningles        = { s_token, c_tokens },
340    meaningless       = { s_token, c_tokens },
341    number            = { s_integer, c_tokens },
342    romannumeral      = { s_integer, c_tokens },
343    semiexpanded      = { s_tokens, c_tokens },
344    string            = { s_token, c_tokens },
345    todimension       = { s_dimension, c_tokens },
346    tohexadecimal     = { s_integer, c_tokens },
347    tointeger         = { s_integer, c_tokens },
348    tomathstyle       = { s_mathstyle, c_tokens },
349    toscaled          = { s_dimension, c_tokens },
350    tosparsedimension = { s_dimension, c_tokens },
351    tosparsescaled    = { s_dimension, c_tokens },
352}
353
354syntax.convert = newsyntax { }  for k in next, result.convert do syntax.convert[k] = "" end
355
356syntax.csname = newsyntax {
357    begincsname  = s_tokens_endcs,
358    csname       = s_tokens_endcs,
359    futurecsname = s_tokens_endcs,
360    lastnamedcs  = false,
361}
362
363syntax.def = newsyntax {
364    cdef       = sequence(s_cs,o_preamble, s_tokens),
365    cdefcsname = sequence(s_tokens_endcs,o_preamble, s_tokens),
366    def        = sequence(s_cs,o_preamble, s_tokens),
367    defcsname  = sequence(s_tokens_endcs,o_preamble, s_tokens),
368    edef       = sequence(s_cs,o_preamble, s_tokens),
369    edefcsname = sequence(s_tokens_endcs,o_preamble, s_tokens),
370    gdef       = sequence(s_cs,o_preamble, s_tokens),
371    gdefcsname = sequence(s_tokens_endcs,o_preamble, s_tokens),
372    xdef       = sequence(s_cs,o_preamble, s_tokens),
373    xdefcsname = sequence(s_tokens_endcs,o_preamble, s_tokens),
374}
375
376result.definecharcode = newresult {
377    Udelcode  = { s_integer, s_integer }, -- todo
378    Umathcode = { s_integer, s_integer }, -- todo
379    amcode    = { s_integer, s_integer },
380    catcode   = { s_integer, s_integer },
381    cccode    = { s_integer, s_integer },
382    delcode   = { s_integer, s_integer }, -- todo
383    hccode    = { s_integer, s_integer },
384    hmcode    = { s_integer, s_integer },
385    lccode    = { s_integer, s_integer },
386    mathcode  = { s_integer, s_integer }, -- todo
387    sfcode    = { s_integer, s_integer },
388    uccode    = { s_integer, s_integer },
389}
390
391syntax.definecharcode = setsyntaxfromresult(result.definecharcode)
392
393syntax.definefamily = newsyntax {
394    scriptfont       = sequence(s_family,s_font),
395    scriptscriptfont = sequence(s_family,s_font),
396    textfont         = sequence(s_family,s_font),
397}
398
399result.definefamily = setdefaultresult(syntax.definefamily, { s_family, s_integer })
400
401syntax.definefont = newsyntax {
402    font = sequence(s_cs,s_filename,optional(choice(sequence("at",s_dimension),sequence("scaled",s_integer)))),
403}
404
405result.definefont = newresult {
406    font = r_tokens
407}
408
409syntax.delimiternumber = newsyntax {
410    delimiter  = s_integer,
411    Udelimiter = sequence(s_integer,s_integer,s_integer),
412}
413
414syntax.discretionary = newsyntax {
415    ["-"]                   = false,
416    automaticdiscretionary  = false,
417    discretionary           = sequence(
418        optional(keyword("penalty"),s_integer),
419        optional(keyword("postword")),
420        optional(keyword("preword")),
421        optional(keyword("break")),
422        optional(keyword("nobreak")),
423        optional(keyword("options"),s_integer),
424        optional(keyword("class"),s_integer),
425        sequence(s_tokens,s_tokens,s_tokens)
426    ),
427    explicitdiscretionary   = false,
428}
429
430syntax.endcsname = newsyntax {
431    endcsname = false,
432}
433
434syntax.endgroup = newsyntax {
435    endgroup       = false,
436    endmathgroup   = false,
437    endsimplegroup = false,
438}
439
440syntax.endjob = newsyntax {
441    ["dump"] = false,
442    ["end"]  = false,
443}
444
445syntax.endlocal = newsyntax {
446    endlocalcontrol = false,
447}
448
449syntax.endparagraph = newsyntax {
450    par           = false,
451    localbreakpar = false,
452}
453
454syntax.endtemplate = newsyntax {
455    aligncontent = false,
456    cr           = false,
457    crcr         = false,
458    noalign      = s_tokens,
459    omit         = false,
460    realign      = sequence(s_tokens,s_tokens),
461    span         = false,
462}
463
464syntax.equationnumber = newsyntax {
465    eqno  = s_tokens,
466    leqno = s_tokens,
467}
468
469syntax.expandafter = newsyntax {
470    expand                  = s_token,
471    expandactive            = s_token,
472    expandafter             = sequence(s_token,s_token),
473    expandafterpars         = s_token,
474    expandafterspaces       = s_token,
475    expandcstoken           = s_token,
476    expandedafter           = sequence(s_token,s_tokens),
477    expandparameter         = s_integer,
478    expandtoken             = s_token,
479    expandtoks              = s_tokens,
480    futureexpand            = sequence(s_token,s_token,s_token),
481    futureexpandafterspaces = sequence(s_token,s_token,s_token),
482    futureexpandafterpars   = sequence(s_token,s_token,s_token),
483    futureexpandis          = s_todo,
484    futureexpandisap        = s_todo,
485    semiexpand              = s_token,
486    unless                  = false,
487}
488
489syntax.explicitspace = newsyntax {
490    [" "]         = false,
491    explicitspace = false,
492
493}
494
495syntax.getmark = newsyntax {
496    botmark         = false,
497    botmarks        = s_integer,
498    currentmarks    = s_integer,
499    firstmark       = false,
500    firstmarks      = s_integer,
501    splitbotmark    = false,
502    splitbotmarks   = s_integer,
503    splitfirstmark  = false,
504    splitfirstmarks = s_integer,
505    topmark         = false,
506    topmarks        = s_integer,
507}
508
509syntax.halign = newsyntax {
510    halign = sequence(
511        optional(sequence(keyword("attr"),s_integer,s_integer)),
512        optional(sequence(keyword("callback"),s_integer)),
513        optional(sequence(keyword("callbacks"),s_integer)),
514        optional(keyword("discard")),
515        optional(keyword("noskips")),
516        optional(keyword("reverse")),
517        optional(sequence(keyword("to"),s_dimension)),
518        optional(sequence(keyword("spread"),s_dimension)),
519        s_tokens
520    ),
521}
522
523syntax.hmove = newsyntax {
524    moveleft  = sequence(s_dimension,s_box),
525    moveright = sequence(s_dimension,s_box),
526}
527
528syntax.hyphenation = newsyntax {
529    hjcode           = sequence(s_integer,o_equal,s_integer),
530    hyphenation      = s_tokens,
531    hyphenationmin   = sequence(o_equal,s_integer),
532    patterns         = s_tokens,
533    postexhyphenchar = sequence(o_equal,s_integer),
534    posthyphenchar   = sequence(o_equal,s_integer),
535    preexhyphenchar  = sequence(o_equal,s_integer),
536    prehyphenchar    = sequence(o_equal,s_integer),
537}
538
539result.hyphenation = newresult {
540    -- TODO
541}
542
543local common_rule = sequence(
544    optional(sequence(keyword("attr"),s_integer,o_equal,s_integer)),
545    optional(sequence(keyword("width"),s_dimension)),
546    optional(sequence(keyword("height"),s_dimension)),
547    optional(sequence(keyword("depth"),s_dimension)),
548    optional(sequence(keyword("xoffset"),s_dimension)),
549    optional(sequence(keyword("yoffset"),s_dimension))
550)
551
552local normal_rule = sequence(common_rule,
553    optional(sequence(keyword("left"),s_dimension)),
554    optional(sequence(keyword("right"),s_dimension)),
555    optional(sequence(keyword("top"),s_dimension)),
556    optional(sequence(keyword("bottom"),s_dimension))
557)
558
559local strut_rule = sequence(common_rule,sequence(
560    optional(sequence(keyword("font"),s_integer)),
561    optional(sequence(keyword("fam"),s_integer)),
562    optional(sequence(keyword("char"),s_integer))
563))
564
565syntax.hrule = newsyntax {
566    nohrule      = normal_rule,
567    virtualhrule = normal_rule,
568    hrule        = normal_rule,
569}
570
571syntax.hskip = newsyntax {
572    hfil    = false,
573    hfill   = false,
574    hfilneg = false,
575    hskip   = sequence(
576        s_dimension,
577        optional(sequence(keyword("plus"),choice(s_dimension,s_filler))),
578        optional(sequence(keyword("minus"),choice(s_dimension,s_filler)))
579    ),
580    hss     = false,
581}
582
583-- needs checking, first version
584
585syntax.iftest = newsyntax {
586    ["else"]        = false,
587    ["fi"]          = false,
588    ["if"]          = false,
589    ifabsdim        = sequence(s_dimension,s_comparison,s_dimension),
590    ifabsfloat      = sequence(s_float,s_comparison,s_float),
591    ifabsnum        = sequence(s_integer,s_comparison,s_integer),
592    ifarguments     = false,
593    ifboolean       = s_integer,
594    ifcase          = s_integer,
595    ifcat           = s_token,
596    ifchkdim        = s_tokens_or,
597    ifchkdimension  = s_tokens_or,
598    ifchkdimexpr    = s_tokens_or,
599    ifchknum        = s_tokens_or,
600    ifchknumber     = s_tokens_or,
601    ifchknumexpr    = s_tokens_or,
602    ifcmpdim        = sequence(s_dimension,s_dimension),
603    ifcmpnum        = sequence(s_integer,s_integer),
604    ifcondition     = s_conditional,
605    ifcramped       = false,
606    ifcsname        = s_tokens_endcs,
607    ifcstok         = s_tokens_relax,
608    ifdefined       = s_token,
609    ifdim           = sequence(s_dimension,s_comparison,s_dimension),
610    ifdimexpression = s_tokens_relax,
611    ifdimval        = s_tokens_or,
612    ifempty         = choice(s_token,s_tokens),
613    iffalse         = false,
614    ifflags         = s_cs,
615    iffloat         = sequence(s_float,s_comparison,s_float),
616    iffontchar      = sequence(s_integer,s_integer),
617    ifhaschar       = sequence(s_token,s_tokens),
618    ifhastok        = sequence(s_token,s_tokens),
619    ifhastoks       = s_tokens_relax,
620    ifhasxtoks      = s_tokens_relax,
621    ifhbox          = s_boxreference,
622    ifhmode         = false,
623    ifinalignment   = false,
624    ifincsname      = s_tokens_endcs,
625    ifinner         = false,
626    ifinsert        = s_integer,
627    ifintervaldim   = sequence(s_dimension,s_dimension,s_dimension),
628    ifintervalfloat = sequence(s_integer,s_integer,s_integer),
629    ifintervalnum   = sequence(s_float,s_float,s_float),
630    iflastnamedcs   = false,
631    iflist          = s_boxreference,
632    ifmathparameter = s_integer,
633    ifmathstyle     = s_mathstyle,
634    ifmmode         = false,
635    ifnum           = sequence(s_integer,s_comparison,s_integer),
636    ifnumexpression = s_tokens_relax,
637    ifnumval        = s_tokens_or,
638    ifodd           = s_integer,
639    ifparameter     = s_parameter_or,
640    ifparameters    = false,
641    ifrelax         = s_token,
642    iftok           = s_tokens_relax,
643    iftrue          = false,
644    ifvbox          = s_boxreference,
645    ifvmode         = false,
646    ifvoid          = s_boxreference,
647    ifx             = s_token,
648    ifzerodim       = s_dimension,
649    ifzerofloat     = s_float,
650    ifzeronum       = s_integer,
651    ["or"]          = false,
652    ["orelse"]      = false,
653    ["orunless"]    = false,
654}
655
656syntax.ignoresomething = newsyntax {
657    ignorearguments  = false,
658    ignorenestedupto = s_token,
659    ignorepars       = false,
660    ignorerest       = false,
661    ignorespaces     = false,
662    ignoreupto       = s_token,
663}
664
665-- result.ignoresomething = newresult {
666--     -- TODO
667-- }
668
669syntax.input = newsyntax {
670    endinput      = false,
671    input         = s_filename,
672    eofinput      = sequence(s_tokens, s_filename),
673    scantokens    = s_tokens,
674    scantextokens = s_tokens,
675    tokenized     = s_tokens,
676    quitloop      = false,
677    quitloopnow   = false,
678    retokenized   = sequence(optional(keyword("catcodetable")),s_tokens),
679}
680
681syntax.insert = newsyntax {
682    insert = s_integer
683}
684
685result.internaldimension = {
686    balanceemergencyshrink   = r_dimension, -- reserved
687    balanceemergencystretch  = r_dimension,
688    balancelineheight        = r_dimension, -- reserved
689    balancevsize             = r_dimension,
690    boxmaxdepth              = r_dimension,
691    delimitershortfall       = r_dimension,
692    displayindent            = r_dimension,
693    displaywidth             = r_dimension,
694    emergencyextrastretch    = r_dimension,
695    emergencystretch         = r_dimension,
696    glyphxoffset             = r_dimension,
697    glyphyoffset             = r_dimension,
698    hangindent               = r_dimension,
699    hfuzz                    = r_dimension,
700    hsize                    = r_dimension,
701    ignoredepthcriterion     = r_dimension,
702    lineskiplimit            = r_dimension,
703    mathsurround             = r_dimension,
704    maxdepth                 = r_dimension,
705    nulldelimiterspace       = r_dimension,
706    overfullrule             = r_dimension,
707    pageextragoal            = r_dimension,
708    parindent                = r_dimension,
709    predisplaysize           = r_dimension,
710    pxdimen                  = r_dimension,
711    scriptspace              = r_dimension,
712    shortinlinemaththreshold = r_dimension,
713    splitextraheight         = r_dimension,
714    splitmaxdepth            = r_dimension,
715    tabsize                  = r_dimension,
716    vfuzz                    = r_dimension,
717    vsize                    = r_dimension,
718}
719
720syntax.internaldimension = setsyntaxfromresult(result.internaldimension)
721
722result.internalglue = {
723    abovedisplayshortskip = r_glue,
724    abovedisplayskip      = r_glue,
725    additionalpageskip    = r_glue,
726    baselineskip          = r_glue,
727    balancebottomskip     = r_glue,
728    balancetopskip        = r_glue,
729    belowdisplayshortskip = r_glue,
730    belowdisplayskip      = r_glue,
731    bottomskip            = r_glue, -- reserved
732    emergencyleftskip     = r_glue,
733    emergencyrightskip    = r_glue,
734    initialpageskip       = r_glue,
735    initialtopskip        = r_glue,
736    leftskip              = r_glue,
737    lineskip              = r_glue,
738    mathsurroundskip      = r_glue,
739    maththreshold         = r_glue,
740    parfillleftskip       = r_glue,
741    parfillrightskip      = r_glue,
742    parfillskip           = r_glue,
743    parinitleftskip       = r_glue,
744    parinitrightskip      = r_glue,
745    parskip               = r_glue,
746    rightskip             = r_glue,
747    spaceskip             = r_glue,
748    splittopskip          = r_glue,
749    tabskip               = r_glue,
750    topskip               = r_glue,
751    xspaceskip            = r_glue,
752}
753
754syntax.internalglue = setsyntaxfromresult(result.internalglue)
755
756result.internalinteger = {
757    adjdemerits              = r_integer,
758    adjustspacing            = r_integer,
759    adjustspacingshrink      = r_integer,
760    adjustspacingstep        = r_integer,
761    adjustspacingstretch     = r_integer,
762    alignmentcellsource      = r_integer,
763    alignmentwrapsource      = r_integer,
764    automatichyphenpenalty   = r_integer,
765    automigrationmode        = r_integer,
766    autoparagraphmode        = r_integer,
767    balanceadjdemerits       = r_integer,
768    balancebreakpasses       = r_integer,
769    balancechecks            = r_integer,
770    balancelooseness         = r_integer,
771    balancepenalty           = r_integer,
772    balancetolerance         = r_integer,
773    binoppenalty             = r_integer,
774    boxlimitmode             = r_integer,
775    brokenpenalty            = r_integer,
776    catcodetable             = r_integer,
777    clubpenalty              = r_integer,
778    day                      = r_integer,
779    defaulthyphenchar        = r_integer,
780    defaultskewchar          = r_integer,
781    delimiterfactor          = r_integer,
782    discretionaryoptions     = r_integer,
783    displaywidowpenalty      = r_integer,
784    doubleadjdemerits        = r_integer,
785    doublehyphendemerits     = r_integer,
786    doublepenaltymode        = r_integer,
787    endlinechar              = r_integer,
788    errorcontextlines        = r_integer,
789    escapechar               = r_integer,
790    eufactor                 = r_integer,
791    etexexprmode             = r_integer,
792    exceptionpenalty         = r_integer,
793    exhyphenchar             = r_integer,
794    exhyphenpenalty          = r_integer,
795    explicithyphenpenalty    = r_integer,
796    fam                      = r_integer,
797    finalhyphendemerits      = r_integer,
798    firstvalidlanguage       = r_integer,
799    floatingpenalty          = r_integer,
800    globaldefs               = r_integer,
801    glyphdatafield           = r_integer,
802    glyphoptions             = r_integer,
803    glyphscale               = r_integer,
804    glyphscriptfield         = r_integer,
805    glyphscriptscale         = r_integer,
806    glyphscriptscriptscale   = r_integer,
807    glyphslant               = r_integer,
808    glyphstatefield          = r_integer,
809    glyphtextscale           = r_integer,
810    glyphxscale              = r_integer,
811    glyphyscale              = r_integer,
812    glyphweight              = r_integer,
813    hangafter                = r_integer,
814    hbadness                 = r_integer,
815    hbadnessmode             = r_integer,
816    holdinginserts           = r_integer,
817    holdingmigrations        = r_integer,
818    hyphenationmode          = r_integer,
819    hyphenpenalty            = r_integer,
820    interlinepenalty         = r_integer,
821    language                 = r_integer,
822    lastlinefit              = r_integer,
823    lefthyphenmin            = r_integer,
824    lefttwindemerits         = r_integer,
825    linebreakchecks          = r_integer,
826    linebreakcriterion       = r_integer,
827    linebreakoptional        = r_integer,
828    linebreakpasses          = r_integer,
829    linedirection            = r_integer,
830    linepenalty              = r_integer,
831    localbrokenpenalty       = r_integer,
832    localinterlinepenalty    = r_integer,
833    localpretolerance        = r_integer,
834    localtolerance           = r_integer,
835    looseness                = r_integer,
836    luacopyinputnodes        = r_integer,
837    mathbeginclass           = r_integer,
838    mathcheckfencesmode      = r_integer,
839    mathdictgroup            = r_integer,
840    mathdictproperties       = r_integer,
841    mathdirection            = r_integer,
842    mathdisplaymode          = r_integer,
843    mathdisplaypenaltyfactor = r_integer,
844    mathdisplayskipmode      = r_integer,
845    mathdoublescriptmode     = r_integer,
846    mathendclass             = r_integer,
847    matheqnogapstep          = r_integer,
848    mathfontcontrol          = r_integer,
849    mathgluemode             = r_integer,
850    mathgroupingmode         = r_integer,
851    mathinlinepenaltyfactor  = r_integer,
852    mathleftclass            = r_integer,
853    mathlimitsmode           = r_integer,
854    mathnolimitsmode         = r_integer,
855    mathpenaltiesmode        = r_integer,
856    mathpretolerance         = r_integer,
857    mathrightclass           = r_integer,
858    mathrulesfam             = r_integer,
859    mathrulesmode            = r_integer,
860    mathscriptsmode          = r_integer,
861    mathslackmode            = r_integer,
862    mathspacingmode          = r_integer,
863    mathsurroundmode         = r_integer,
864    mathtolerance            = r_integer,
865    maxdeadcycles            = r_integer,
866    month                    = r_integer,
867    newlinechar              = r_integer,
868    normalizelinemode        = r_integer,
869    normalizeparmode         = r_integer,
870    nooutputboxerror         = r_integer,
871    nospaces                 = r_integer,
872    outputbox                = r_integer,
873    outputpenalty            = r_integer,
874    overloadmode             = r_integer,
875    parametermode            = r_integer,
876    pardirection             = r_integer,
877    pausing                  = r_integer,
878    postdisplaypenalty       = r_integer,
879    postinlinepenalty        = r_integer,
880    postshortinlinepenalty   = r_integer,
881    prebinoppenalty          = r_integer,
882    predisplaydirection      = r_integer,
883    predisplaygapfactor      = r_integer,
884    predisplaypenalty        = r_integer,
885    preinlinepenalty         = r_integer,
886    prerelpenalty            = r_integer,
887    preshortinlinepenalty    = r_integer,
888    pretolerance             = r_integer,
889    protrudechars            = r_integer,
890    relpenalty               = r_integer,
891    righthyphenmin           = r_integer,
892    righttwindemerits        = r_integer,
893    savinghyphcodes          = r_integer,
894    savingvdiscards          = r_integer,
895    scriptspaceafterfactor   = r_integer,
896    scriptspacebeforefactor  = r_integer,
897    scriptspacebetweenfactor = r_integer,
898    setfontid                = r_integer,
899    setlanguage              = r_integer,
900    shapingpenaltiesmode     = r_integer,
901    shapingpenalty           = r_integer,
902    shortinlineorphanpenalty = r_integer,
903    showboxbreadth           = r_integer,
904    showboxdepth             = r_integer,
905    shownodedetails          = r_integer,
906    singlelinepenalty        = r_integer,
907    spacechar                = r_integer,
908    spacefactormode          = r_integer,
909    spacefactoroverload      = r_integer,
910    spacefactorshrinklimit   = r_integer,
911    spacefactorstretchlimit  = r_integer,
912    supmarkmode              = r_integer,
913    textdirection            = r_integer,
914    time                     = r_integer,
915    tolerance                = r_integer,
916    tracingadjusts           = r_integer,
917    tracingalignments        = r_integer,
918    tracingassigns           = r_integer,
919    tracingbalancing         = r_integer,
920    tracingcommands          = r_integer,
921    tracingexpressions       = r_integer,
922    tracingfitness           = r_integer,
923    tracingfullboxes         = r_integer,
924    tracinggroups            = r_integer,
925    tracinghyphenation       = r_integer,
926    tracingifs               = r_integer,
927    tracinginserts           = r_integer,
928    tracinglevels            = r_integer,
929    tracinglists             = r_integer,
930    tracingloners            = r_integer,
931    tracinglooseness         = r_integer,
932    tracinglostchars         = r_integer,
933    tracingmacros            = r_integer,
934    tracingmarks             = r_integer,
935    tracingmath              = r_integer,
936    tracingmvl               = r_integer,
937    tracingnesting           = r_integer,
938    tracingnodes             = r_integer,
939    tracingonline            = r_integer,
940    tracingorphans           = r_integer,
941    tracingoutput            = r_integer,
942    tracingpages             = r_integer,
943    tracingparagraphs        = r_integer,
944    tracingpasses            = r_integer,
945    tracingpenalties         = r_integer,
946    tracingrestores          = r_integer,
947    tracingstats             = r_integer,
948    tracingtoddlers          = r_integer,
949    uchyph                   = r_integer,
950    variablefam              = r_integer,
951    vbadness                 = r_integer,
952    vbadnessmode             = r_integer,
953    vsplitchecks             = r_integer,
954    widowpenalty             = r_integer,
955    year                     = r_integer,
956}
957
958syntax.internalinteger = setsyntaxfromresult(result.internalinteger)
959
960result.internalmuglue = {
961    medmuskip   = r_muglue,
962    pettymuskip = r_muglue,
963    thickmuskip = r_muglue,
964    thinmuskip  = r_muglue,
965    tinymuskip  = r_muglue,
966}
967
968syntax.internalmuglue = setsyntaxfromresult(result.internalmuglue)
969
970result.internaltoks = {
971    errhelp        = r_toks,
972    everybeforepar = r_toks,
973    everycr        = r_toks,
974    everydisplay   = r_toks,
975    everyeof       = r_toks,
976    everyhbox      = r_toks,
977    everyjob       = r_toks,
978    everymath      = r_toks,
979    everymathatom  = r_toks,
980    everypar       = r_toks,
981    everytab       = r_toks,
982    everyvbox      = r_toks,
983    output         = r_toks,
984}
985
986syntax.internaltoks = setsyntaxfromresult(result.internaltoks)
987
988syntax.italiccorrection = newsyntax {
989    ["/"]                    = false,
990    explicititaliccorrection = false,
991    forcedleftcorrection     = false,
992    forcedrightcorrection    = false,
993    italiccorrection         = false,
994}
995
996syntax.kern = newsyntax {
997    kern  = s_dimension,
998    hkern = s_dimension,
999    vkern = s_dimension,
1000}
1001
1002syntax.leader = newsyntax {
1003    cleaders = sequence(choice(s_box,s_rule,s_glyph),s_glue),
1004    gleaders = sequence(choice(s_box,s_rule,s_glyph),s_glue),
1005    leaders  = sequence(choice(s_box,s_rule,s_glyph),s_glue),
1006    uleaders = sequence(
1007        optional(sequence(keyword("callback"),s_integer)),
1008        optional(keyword("line")),
1009        optional(keyword("nobreak")),
1010        choice(s_box,s_rule,s_glyph),
1011        s_glue
1012    ),
1013    xleaders = sequence(choice(s_box,s_rule,s_glyph),s_glue),
1014}
1015
1016syntax.legacy = newsyntax {
1017    shipout = s_tokens
1018}
1019
1020syntax.let = newsyntax {
1021    futuredef        = sequence(s_cs,s_cs),
1022    futurelet        = sequence(s_cs,o_equal,s_cs),
1023    glet             = s_cs,
1024    gletcsname       = s_tokens_endcs,
1025    glettonothing    = s_cs,
1026    let              = s_cs,
1027    letcharcode      = s_cs,
1028    letcsname        = s_tokens_endcs,
1029    letfrozen        = s_cs,
1030    letprotected     = s_cs,
1031    lettolastnamedcs = s_cs,
1032    lettonothing     = s_cs,
1033    swapcsvalues     = sequence(s_cs,s_cs),
1034    unletfrozen      = s_cs,
1035    unletprotected   = s_cs,
1036}
1037
1038syntax.localbox = newsyntax {
1039    localleftbox    = s_box,
1040    localmiddlebox  = s_box,
1041    localrightbox   = s_box,
1042    resetlocalboxes = false,
1043}
1044
1045syntax.luafunctioncall = newsyntax {
1046    luabytecodecall = s_integer,
1047    luafunctioncall = s_integer,
1048}
1049
1050do
1051
1052    local split = sequence(
1053        optional(keyword("attr"),s_integer,s_integer),
1054        optional(keyword("to"),s_dimension),
1055        optional(keyword("upto"),s_dimension),
1056        s_tokens
1057    )
1058
1059    local make   = sequence(
1060        optional(sequence(keyword("target"),s_integer)),
1061        optional(sequence(keyword("to"),s_dimension)),
1062        optional(sequence(keyword("adapt"),s_scale)),
1063        optional(sequence(keyword("attr"),s_integer,s_integer)),
1064        optional(sequence(keyword("anchor"),s_integer)),
1065        optional(sequence(keyword("axis"),s_integer)),          -- axis and noaxis
1066        optional(sequence(keyword("shift"),s_dimension)),
1067        optional(sequence(keyword("spread"),s_dimension)),
1068        optional(sequence(keyword("source"),s_integer)),
1069        optional(sequence(keyword("direction"),s_integer)),
1070        optional(keyword("delay")),
1071        optional(sequence(keyword("orientation"),s_integer)),
1072        optional(sequence(keyword("xoffset"),s_dimension)),
1073        optional(sequence(keyword("xmove"),s_dimension)),
1074        optional(sequence(keyword("yoffset"),s_dimension)),
1075        optional(sequence(keyword("ymove"),s_dimension)),
1076        optional(keyword("reverse")),
1077        optional(keyword("retain")),
1078        optional(keyword("container")),
1079        optional(keyword("mathtext")),
1080     -- optional(keyword("discarded")),
1081        optional(sequence(keyword("class"),s_integer)),
1082        s_tokens
1083    )
1084
1085    syntax.makebox = newsyntax {
1086        box               = s_boxreference,
1087        copy              = s_boxreference,
1088        dbox              = make,
1089        dpack             = make,
1090        dsplit            = split,
1091        flushmvl          = s_integer,
1092        hbox              = make,
1093        hpack             = make,
1094        insertbox         = s_integer,
1095        insertcopy        = s_integer,
1096        lastbox           = false,
1097        localleftboxbox   = false,
1098        localmiddleboxbox = false,
1099        localrightboxbox  = false,
1100        tpack             = make,
1101        tsplit            = split,
1102        vbalance          = sequence(
1103            optional(keyword("exactly")),
1104            optional(keyword("additional")),
1105            optional(keyword("trial")),
1106            s_boxreference
1107        ),
1108        vbalancedbox      = s_boxreference,
1109        vbalancedtop      = s_boxreference,
1110        vbalancedinsert   = sequence(
1111            s_boxreference,
1112            optional(keyword("index")),
1113            optional(keyword("descend")),
1114            s_integer
1115        ),
1116        vbalanceddiscard  = sequence(
1117            s_boxreference,
1118            optional(keyword("descend")),
1119            optional(keyword("remove"))
1120        ),
1121        vbalanceddeinsert  = sequence(
1122            s_boxreference,
1123            optional(keyword("descend")),
1124            optional(keyword("forceheight")),
1125            optional(keyword("forcedepth"))
1126        ),
1127        vbalancedreinsert  = sequence(
1128            s_boxreference,
1129            optional(keyword("descend"))
1130        ),
1131        vbox              = make,
1132        vpack             = make,
1133        vsplit            = split,
1134        vtop              = make,
1135    }
1136
1137end
1138
1139syntax.mathaccent = newsyntax {
1140    mathaccent  = s_tokens, -- overloaded in conetext
1141    Umathaccent = sequence(
1142        optional(sequence(keyword("attr"),s_integer,s_integer)),
1143        optional(keyword("center")),
1144        optional(sequence(keyword("class"),s_integer)),
1145        optional(keyword("exact")),
1146        optional(sequence(keyword("source"),s_integer)),
1147        optional(keyword("stretch")),
1148        optional(keyword("shrink")),
1149        optional(sequence(keyword("fraction"),s_integer)),
1150        optional(keyword("fixed")),
1151        optional(keyword("keepbase")),
1152        optional(keyword("nooverflow")),
1153        optional(keyword("base")),
1154        choice(
1155            sequence(keyword("both"),optional(keyword("fixed")),s_character,optional(keyword("fixed")),s_character),
1156            sequence(keyword("bottom"),optional(keyword("fixed")),s_character),
1157            sequence(keyword("top"),optional(keyword("fixed")),s_character),
1158            sequence(keyword("overlay"),s_character),
1159            s_character
1160        )
1161    ),
1162}
1163
1164syntax.mathcharnumber = newsyntax {
1165    Umathchar      = s_integer,
1166    mathclass      = s_integer,
1167    mathdictionary = sequence(s_integer,s_mathchar),
1168    mathchar       = s_integer,
1169    nomathchar     = false,
1170}
1171
1172syntax.mathchoice = newsyntax {
1173    mathdiscretionary = sequence(optional(sequence(keyword("class"),s_integer)),s_tokens,s_tokens,s_tokens),
1174    mathstack         = s_tokens,
1175    mathchoice        = sequence(s_tokens,s_tokens,s_tokens,s_tokens),
1176}
1177
1178syntax.mathcomponent = newsyntax {
1179    mathatom  = sequence(
1180        optional(sequence(keyword("attr"),s_integer,s_integer)),
1181        optional(sequence(keyword("all"),s_integer)),
1182        optional(sequence(keyword("leftclass"),s_integer)),
1183        optional(keyword("limits")),
1184        optional(sequence(keyword("rightclass"),s_integer)),
1185        optional(sequence(keyword("class"),s_integer)),
1186        optional(keyword("unpack")),
1187        optional(keyword("unroll")),
1188        optional(keyword("single")),
1189        optional(sequence(keyword("source"),s_integer)),
1190        optional(keyword("textfont")),
1191        optional(keyword("mathfont")),
1192        optional(sequence(keyword("options"),s_integer)),
1193        optional(keyword("nolimits")),
1194        optional(keyword("nooverflow")),
1195        optional(keyword("void")),
1196        optional(keyword("phantom")),
1197        optional(keyword("continuation")),
1198        optional(s_integer)
1199    ),
1200    mathbin   = s_tokens,
1201    mathclose = s_tokens,
1202    mathinner = s_tokens,
1203    mathop    = s_tokens,
1204    mathopen  = s_tokens,
1205    mathord   = s_tokens,
1206    mathpunct = s_tokens,
1207    mathrel   = s_tokens,
1208    overline  = s_tokens,
1209    underline = s_tokens,
1210}
1211
1212do
1213
1214    local fence = sequence(
1215        optional(keyword("auto")),
1216        optional(sequence(keyword("attr"),s_integer,s_integer)),
1217        optional(keyword("axis")),
1218        optional(sequence(keyword("bottom"),s_dimension)),
1219        optional(sequence(keyword("depth"),s_dimension)),
1220        optional(sequence(keyword("factor"),s_integer)),
1221        optional(sequence(keyword("height"),s_dimension)),
1222        optional(keyword("noaxis")),
1223        optional(keyword("nocheck")),
1224        optional(keyword("nolimits")),
1225        optional(keyword("nooverflow")),
1226        optional(sequence(keyword("leftclass"),s_integer)),
1227        optional(keyword("limits")),
1228        optional(keyword("exact")),
1229        optional(keyword("void")),
1230        optional(keyword("phantom")),
1231        optional(sequence(keyword("class"),s_integer)),
1232        optional(sequence(keyword("rightclass"),s_integer)),
1233        optional(keyword("scale")),
1234        optional(sequence(keyword("source"),s_integer)),
1235        optional(keyword("top")),
1236        s_delimiter
1237    )
1238
1239    syntax.mathfence = newsyntax {
1240        Uleft        = fence,
1241        Umiddle      = fence,
1242        Uoperator    = fence,
1243        Uright       = fence,
1244        Uvextensible = fence,
1245        left         = fence,
1246        middle       = fence,
1247        right        = fence,
1248    }
1249
1250end
1251
1252do
1253
1254    local options = sequence(
1255        optional(sequence(keyword("attr"),s_integer,s_integer)),
1256        optional(sequence(keyword("class"),s_integer)),
1257        optional(keyword("center")),
1258        optional(keyword("exact")),
1259        optional(keyword("proportional")),
1260        optional(keyword("noaxis")),
1261        optional(keyword("nooverflow")),
1262        optional(sequence(keyword("style"),s_mathstyle)),
1263        optional(sequence(keyword("source"),s_integer)),
1264        optional(sequence(keyword("hfactor"),s_integer)),
1265        optional(sequence(keyword("vfactor"),s_integer)),
1266        optional(keyword("font")),
1267        optional(sequence(keyword("thickness"),s_dimension)),
1268        optional(keyword("usecallback"))
1269    )
1270
1271    -- needs checking
1272
1273    syntax.mathfraction = newsyntax {
1274        Uabove               = sequence(s_dimension,options),
1275        Uabovewithdelims     = sequence(s_delimiter,s_delimiter,s_dimension,options),
1276        Uatop                = sequence(s_dimension,options),
1277        Uatopwithdelims      = sequence(s_delimiter,s_delimiter,s_dimension,options),
1278        Uover                = sequence(options),
1279        Uoverwithdelims      = sequence(s_delimiter,s_delimiter,options),
1280        Uskewed              = sequence(s_delimiter,options),
1281        Uskewedwithdelims    = sequence(s_delimiter,s_delimiter,s_delimiter,options),
1282        Ustretched           = sequence(s_delimiter,options),
1283        Ustretchedwithdelims = sequence(s_delimiter,s_delimiter,s_delimiter,options),
1284        above                = s_dimension,
1285        abovewithdelims      = sequence(s_delimiter,s_delimiter,s_dimension),
1286        atop                 = s_dimension,
1287        atopwithdelims       = sequence(s_delimiter,s_delimiter,s_dimension),
1288        over                 = false,
1289        overwithdelims       = sequence(s_delimiter,s_delimiter),
1290    }
1291
1292end
1293
1294syntax.mathmodifier = newsyntax {
1295    Umathadapttoleft  = false,
1296    Umathadapttoright = false,
1297    Umathlimits       = false,
1298    Umathnoaxis       = false,
1299    Umathnolimits     = false,
1300    Umathopenupdepth  = s_dimension,
1301    Umathopenupheight = s_dimension,
1302    Umathphantom      = false,
1303    Umathsource       = sequence(optional(s_nucleus),s_integer),
1304    Umathuseaxis      = false,
1305    Umathvoid         = false,
1306    displaylimits     = false,
1307    limits            = false,
1308    nolimits          = false,
1309}
1310
1311do
1312
1313    local options = sequence(
1314        optional(sequence(keyword("attr"),s_integer,s_integer)),
1315        optional(keyword("bottom")),
1316        optional(keyword("exact")),
1317        optional(keyword("top")),
1318        optional(sequence(keyword("style"),s_mathstyle)),
1319        optional(sequence(keyword("source"),s_integer)),
1320        optional(keyword("stretch")),
1321        optional(keyword("shrink")),
1322        optional(sequence(keyword("width"),s_dimension)),
1323        optional(sequence(keyword("height"),s_dimension)),
1324        optional(sequence(keyword("depth"),s_dimension)),
1325        optional(keyword("left")),
1326        optional(keyword("middle")),
1327        optional(keyword("right")),
1328        optional(keyword("nooverflow")),
1329        optional(keyword("usecallback"))
1330    )
1331
1332    syntax.mathradical = newsyntax {
1333        Udelimited      = sequence(options,s_delimiter,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens),
1334        Udelimiterover  = sequence(options,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens),
1335        Udelimiterunder = sequence(options,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens),
1336        Uhextensible    = sequence(options,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens),
1337        Uoverdelimiter  = sequence(options,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens),
1338        Uradical        = sequence(options,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens),
1339        Uroot           = sequence(options,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens,s_mathtokens),
1340        Urooted         = sequence(options,s_delimiter,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens,s_mathtokens),
1341        Uunderdelimiter = sequence(options,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens),
1342        radical         = sequence(options,s_delimiter,optional(s_delimiter),optional(s_delimiter),s_mathtokens,s_mathtokens),
1343    }
1344
1345end
1346
1347syntax.mathscript = newsyntax {
1348    indexedsubprescript   = s_mathtokens,
1349    indexedsubscript      = s_mathtokens,
1350    indexedsuperprescript = s_mathtokens,
1351    indexedsuperscript    = s_mathtokens,
1352    noatomruling          = false,
1353    nonscript             = false,
1354    noscript              = false,
1355    nosubprescript        = false,
1356    nosubscript           = false,
1357    nosuperprescript      = false,
1358    nosuperscript         = false,
1359    primescript           = s_mathtokens,
1360    subprescript          = s_mathtokens,
1361    subscript             = s_mathtokens,
1362    superprescript        = s_mathtokens,
1363    superscript           = s_mathtokens,
1364}
1365
1366syntax.mathshiftcs = newsyntax {
1367    Ustartdisplaymath = false,
1368    Ustartmath        = false,
1369    Ustartmathmode    = false,
1370    Ustopdisplaymath  = false,
1371    Ustopmath         = false,
1372    Ustopmathmode     = false,
1373}
1374
1375syntax.mathstyle = newsyntax {
1376    givenmathstyle           = s_mathstyle,
1377    allcrampedstyles         = false,
1378    alldisplaystyles         = false,
1379    allmainstyles            = false,
1380    allmathstyles            = false,
1381    allscriptscriptstyles    = false,
1382    allscriptstyles          = false,
1383    allsplitstyles           = false,
1384    alltextstyles            = false,
1385    alluncrampedstyles       = false,
1386    allunsplitstyles         = false,
1387    crampeddisplaystyle      = false,
1388    crampedscriptscriptstyle = false,
1389    crampedscriptstyle       = false,
1390    crampedtextstyle         = false,
1391    currentlysetmathstyle    = false,
1392    displaystyle             = false,
1393    scaledmathstyle          = s_integer,
1394    scriptscriptstyle        = false,
1395    scriptstyle              = false,
1396    textstyle                = false,
1397}
1398
1399result.mathstyle = setdefaultresult(result.mathstyle, r_integer)
1400
1401result.mathstyle.Ustyle          = { s_mathstyle, s_integer }
1402result.mathstyle.scaledmathstyle = { s_mathstyle, s_integer }
1403
1404syntax.message = newsyntax {
1405    message    = s_tokens,
1406    errmessage = s_tokens,
1407}
1408
1409syntax.mkern = newsyntax {
1410    mkern = s_dimension
1411}
1412
1413syntax.mskip = newsyntax {
1414    mathatomskip = s_muglue,
1415    mskip        = s_muglue,
1416}
1417
1418syntax.mvl = newsyntax {
1419    beginmvl = sequence(
1420        optional(sequence(keyword("index"),s_integer)),
1421        optional(sequence(keyword("options"),s_integer)),
1422        optional(sequence(keyword("prevdepth"),s_dimension)),
1423        optional(s_integer)
1424    ),
1425    endmvl   = s_integer,
1426}
1427
1428syntax.noexpand = newsyntax {
1429    noexpand = s_token
1430}
1431
1432syntax.parameter = newsyntax {
1433    alignmark     = false,
1434    parametermark = false,
1435}
1436
1437syntax.penalty = newsyntax {
1438    hpenalty = s_integer,
1439    penalty  = s_integer,
1440    vpenalty = s_integer,
1441}
1442
1443syntax.prefix = newsyntax {
1444    aliased       = false,
1445    constant      = false,
1446    constrained   = false,
1447    deferred      = false,
1448    enforced      = false,
1449    frozen        = false,
1450    global        = false,
1451    immediate     = false,
1452    immutable     = false,
1453    inherited     = false,
1454    instance      = false,
1455    long          = false,
1456    mutable       = false,
1457    noaligned     = false,
1458    outer         = false,
1459    overloaded    = false,
1460    permanent     = false,
1461    protected     = false,
1462    retained      = false,
1463    semiprotected = false,
1464    tolerant      = false,
1465    untraced      = false,
1466}
1467
1468syntax.register = newsyntax {
1469    count     = sequence(s_boxreference,o_equal,s_integer),
1470    attribute = sequence(s_boxreference,o_equal,s_integer),
1471    dimen     = sequence(s_boxreference,o_equal,s_dimension),
1472    skip      = sequence(s_boxreference,o_equal,s_glue),
1473    muskip    = sequence(s_boxreference,o_equal,s_muglue),
1474    toks      = sequence(s_boxreference,o_equal,s_tokens),
1475    float     = sequence(s_boxreference,o_equal,s_float),
1476}
1477
1478result.register = newresult {
1479    count     =  { s_boxreference, s_integer },
1480    attribute =  { s_boxreference, s_integer },
1481    dimen     =  { s_boxreference, s_dimension },
1482    skip      =  { s_boxreference, s_glue },
1483    muskip    =  { s_boxreference, s_muglue },
1484    toks      =  { s_boxreference, s_tokens },
1485    float     =  { s_boxreference, s_float },
1486}
1487
1488syntax.relax = newsyntax {
1489    norelax = false,
1490    relax   = false,
1491}
1492
1493syntax.removeitem = newsyntax {
1494    unboundary = false,
1495    unkern     = false,
1496    unpenalty  = false,
1497    unskip     = false,
1498}
1499
1500syntax.auxiliary = newsyntax {
1501    insertmode      = s_integer,
1502    interactionmode = s_integer,
1503    prevdepth       = s_dimension,
1504    prevgraf        = s_integer,
1505    spacefactor     = s_integer,
1506}
1507
1508result.auxiliary = newresult {
1509    insertmode      = r_integer,
1510    interactionmode = r_integer,
1511    prevdepth       = r_dimension,
1512    prevgraf        = r_integer,
1513    spacefactor     = r_integer,
1514}
1515
1516syntax.setbox = newsyntax {
1517    setbox = sequence(s_boxreference,o_equal,o_box)
1518}
1519
1520syntax.boxproperty = newsyntax {
1521    boxadapt       = sequence(s_boxreference,o_equal,s_integer), -- scaled
1522    boxanchor      = sequence(s_boxreference,o_equal,s_integer),
1523    boxanchors     = sequence(s_boxreference,o_equal,s_integer,s_integer), -- check
1524    boxattribute   = sequence(s_boxreference,s_integer,o_equal,s_integer),
1525    boxdirection   = sequence(s_boxreference,o_equal,s_integer),
1526    boxfreeze      = sequence(s_boxreference,o_equal,s_integer),
1527    boxfinalize    = sequence(s_boxreference,o_equal,s_integer),
1528    boxgeometry    = sequence(s_boxreference,o_equal,s_integer),
1529    boxinserts     = sequence(s_boxreference,o_equal,s_integer),
1530    boxlimit       = s_boxreference,
1531    boxlimitate    = sequence(s_boxreference,o_equal,s_integer),
1532    boxmigrate     = sequence(s_boxreference,o_equal,s_integer),
1533    boxorientation = sequence(s_boxreference,o_equal,s_integer),
1534    boxrepack      = s_boxreference,
1535    boxshift       = sequence(s_boxreference,o_equal,s_dimension),
1536    boxshrink      = s_boxreference,
1537    boxsource      = sequence(s_boxreference,o_equal,s_integer),
1538    boxstretch     = s_boxreference,
1539    boxsubtype     = s_boxreference,
1540    boxtarget      = sequence(s_boxreference,o_equal,s_integer),
1541    boxtotal       = s_boxreference,
1542    boxvadjust     = sequence(s_boxreference,s_tokens), -- todo: pre/post etc
1543    boxxmove       = sequence(s_boxreference,o_equal,s_dimension),
1544    boxxoffset     = sequence(s_boxreference,o_equal,s_dimension),
1545    boxymove       = sequence(s_boxreference,o_equal,s_dimension),
1546    boxyoffset     = sequence(s_boxreference,o_equal,s_dimension),
1547    dp             = sequence(s_boxreference,o_equal,s_dimension),
1548    ht             = sequence(s_boxreference,o_equal,s_dimension),
1549    wd             = sequence(s_boxreference,o_equal,s_dimension),
1550}
1551
1552-- boxadapt   : zero
1553-- boxfreeze  : width or total
1554-- boxrepack  : width or total
1555-- boxvadjust : 0x1 = preadjust 0x2 = postadjust 0x4 = premigrate 0x8 = postmigrate
1556
1557result.boxproperty = newresult {
1558    boxadapt       = { s_boxreference, s_dimension },
1559    boxanchor      = { s_boxreference, s_integer },
1560    boxanchors     = { s_boxreference, s_integer },
1561    boxattribute   = { sequence(s_boxreference,s_integer), s_integer },
1562    boxdirection   = { s_boxreference, s_integer },
1563    boxfreeze      = { s_boxreference, s_integer },
1564    boxgeometry    = { s_boxreference, s_integer },
1565    boxlimitate    = { s_boxreference, s_integer },
1566    boxorientation = { s_boxreference, s_integer },
1567    boxrepack      = { s_boxreference, s_dimension },
1568    boxshift       = { s_boxreference, s_dimension },
1569    boxshrink      = { s_boxreference, s_dimension },
1570    boxsource      = { s_boxreference, s_integer },
1571    boxstretch     = { s_boxreference, s_dimension },
1572    boxtarget      = { s_boxreference, s_integer },
1573    boxtotal       = { s_boxreference, s_dimension },
1574    boxvadjust     = { s_boxreference, s_cardinal },
1575    boxxmove       = { s_boxreference, s_dimension },
1576    boxxoffset     = { s_boxreference, s_dimension },
1577    boxymove       = { s_boxreference, s_dimension },
1578    boxyoffset     = { s_boxreference, s_dimension },
1579    dp             = { s_boxreference, s_dimension },
1580    ht             = { s_boxreference, s_dimension },
1581    wd             = { s_boxreference, s_dimension },
1582}
1583
1584syntax.setfont = newsyntax {
1585    nullfont = false,
1586}
1587
1588result.setresult.setfont = newresult {
1589    nullfont = r_tokens,
1590}
1591
1592
1593syntax.fontproperty = newsyntax {
1594    cfcode          = sequence(s_font,s_integer,o_equal,s_integer),
1595    efcode          = sequence(s_font,s_integer,o_equal,s_integer),
1596    fontdimen       = sequence(s_font,s_integer,o_equal,s_dimension),
1597    hyphenchar      = sequence(s_font,o_equal,s_integer),
1598    lpcode          = sequence(s_font,s_integer,o_equal,s_dimension),
1599    rpcode          = sequence(s_font,s_integer,o_equal,s_dimension),
1600    scaledfontdimen = sequence(s_font,o_equal,s_integer),
1601    skewchar        = sequence(s_font,o_equal,s_integer),
1602}
1603
1604result.fontproperty = newresult {
1605    cfcode          = { sequence(s_font,s_integer), s_integer },
1606    efcode          = { sequence(s_font,s_integer), s_integer },
1607    fontdimen       = { sequence(s_font,s_integer), s_dimension },
1608    hyphenchar      = { s_font, s_integer },
1609    lpcode          = { sequence(s_font,s_integer), s_dimension },
1610    rpcode          = { sequence(s_font,s_integer), s_dimension },
1611    scaledfontdimen = { s_font, s_integer },
1612    skewchar        = { s_font, s_integer },
1613}
1614
1615syntax.interaction = newsyntax {
1616    batchmode     = false,
1617    errorstopmode = false,
1618    nonstopmode   = false,
1619    scrollmode    = false,
1620}
1621
1622syntax.mark = newsyntax {
1623    clearmarks = s_integer,
1624    flushmarks = false,
1625    mark       = s_tokens,
1626    marks      = sequence(s_integer,s_tokens),
1627    setmarks   = s_integer,
1628}
1629
1630
1631do
1632
1633    local dimension = { s_mathstyle, s_dimension }
1634    local integer   = { s_mathstyle, s_integer }
1635    local variant   = { "", s_mathstyle }
1636
1637
1638    result.mathparameter = newresult {
1639        Umathaccentbasedepth                = dimension,
1640        Umathaccentbaseheight               = dimension,
1641        Umathaccentbottomovershoot          = dimension,
1642        Umathaccentbottomshiftdown          = dimension,
1643        Umathaccentextendmargin             = dimension,
1644        Umathaccentsuperscriptdrop          = dimension,
1645        Umathaccentsuperscriptpercent       = integer,
1646        Umathaccenttopovershoot             = dimension,
1647        Umathaccenttopshiftup               = dimension,
1648        Umathaccentvariant                  = variant,
1649        Umathaxis                           = dimension,
1650        Umathbottomaccentvariant            = variant,
1651        Umathconnectoroverlapmin            = dimension,
1652        Umathdegreevariant                  = variant,
1653        Umathdelimiterextendmargin          = dimension,
1654        Umathdelimiterovervariant           = variant,
1655        Umathdelimiterpercent               = integer,
1656        Umathdelimitershortfall             = dimension,
1657        Umathdelimiterundervariant          = variant,
1658        Umathdenominatorvariant             = variant,
1659        Umathexheight                       = dimension,
1660        Umathextrasubpreshift               = dimension,
1661        Umathextrasubprespace               = dimension,
1662        Umathextrasubshift                  = dimension,
1663        Umathextrasubspace                  = dimension,
1664        Umathextrasuppreshift               = dimension,
1665        Umathextrasupprespace               = dimension,
1666        Umathextrasupshift                  = dimension,
1667        Umathextrasupspace                  = dimension,
1668        Umathflattenedaccentbasedepth       = dimension,
1669        Umathflattenedaccentbaseheight      = dimension,
1670        Umathflattenedaccentbottomshiftdown = dimension,
1671        Umathflattenedaccenttopshiftup      = dimension,
1672        Umathfractiondelsize                = dimension,
1673        Umathfractiondenomdown              = dimension,
1674        Umathfractiondenomvgap              = dimension,
1675        Umathfractionnumup                  = dimension,
1676        Umathfractionnumvgap                = dimension,
1677        Umathfractionrule                   = dimension,
1678        Umathfractionvariant                = variant,
1679        Umathhextensiblevariant             = variant,
1680        Umathlimitabovebgap                 = dimension,
1681        Umathlimitabovekern                 = dimension,
1682        Umathlimitabovevgap                 = dimension,
1683        Umathlimitbelowbgap                 = dimension,
1684        Umathlimitbelowkern                 = dimension,
1685        Umathlimitbelowvgap                 = dimension,
1686        Umathnolimitsubfactor               = integer,
1687        Umathnolimitsupfactor               = integer,
1688        Umathnumeratorvariant               = variant,
1689        Umathoperatorsize                   = dimension,
1690        Umathoverbarkern                    = dimension,
1691        Umathoverbarrule                    = dimension,
1692        Umathoverbarvgap                    = dimension,
1693        Umathoverdelimiterbgap              = dimension,
1694        Umathoverdelimitervariant           = variant,
1695        Umathoverdelimitervgap              = dimension,
1696        Umathoverlayaccentvariant           = variant,
1697        Umathoverlinevariant                = variant,
1698        Umathprimeraise                     = dimension,
1699        Umathprimeraisecomposed             = dimension,
1700        Umathprimeshiftdrop                 = dimension,
1701        Umathprimeshiftup                   = dimension,
1702        Umathprimespaceafter                = dimension,
1703        Umathprimevariant                   = variant,
1704        Umathquad                           = dimension,
1705        Umathradicaldegreeafter             = dimension,
1706        Umathradicaldegreebefore            = dimension,
1707        Umathradicaldegreeraise             = dimension,
1708        Umathradicalextensibleafter         = dimension,
1709        Umathradicalextensiblebefore        = dimension,
1710        Umathradicalkern                    = dimension,
1711        Umathradicalrule                    = dimension,
1712        Umathradicalvariant                 = variant,
1713        Umathradicalvgap                    = dimension,
1714        Umathruledepth                      = dimension,
1715        Umathruleheight                     = dimension,
1716        Umathskeweddelimitertolerance       = dimension,
1717        Umathskewedfractionhgap             = dimension,
1718        Umathskewedfractionvgap             = dimension,
1719        Umathspaceafterscript               = dimension,
1720        Umathspacebeforescript              = dimension,
1721        Umathspacebetweenscript             = dimension,
1722        Umathstackdenomdown                 = dimension,
1723        Umathstacknumup                     = dimension,
1724        Umathstackvariant                   = variant,
1725        Umathstackvgap                      = dimension,
1726        Umathsubscriptsnap                  = dimension,
1727        Umathsubscriptvariant               = variant,
1728        Umathsubshiftdown                   = dimension,
1729        Umathsubshiftdrop                   = dimension,
1730        Umathsubsupshiftdown                = dimension,
1731        Umathsubsupvgap                     = dimension,
1732        Umathsubtopmax                      = dimension,
1733        Umathsupbottommin                   = dimension,
1734        Umathsuperscriptsnap                = dimension,
1735        Umathsuperscriptvariant             = dimension,
1736        Umathsupshiftdrop                   = dimension,
1737        Umathsupshiftup                     = dimension,
1738        Umathsupsubbottommax                = dimension,
1739        Umathtopaccentvariant               = variant,
1740        Umathunderbarkern                   = dimension,
1741        Umathunderbarrule                   = dimension,
1742        Umathunderbarvgap                   = dimension,
1743        Umathunderdelimiterbgap             = dimension,
1744        Umathunderdelimitervariant          = variant,
1745        Umathunderdelimitervgap             = dimension,
1746        Umathunderlinevariant               = variant,
1747        Umathvextensiblevariant             = variant,
1748        Umathxscale                         = integer,
1749        Umathyscale                         = integer,
1750
1751        copymathatomrule                    = false, -- todo
1752        copymathparent                      = false, -- todo
1753        copymathspacing                     = false, -- todo
1754        letmathatomrule                     = false, -- todo
1755        letmathparent                       = false, -- todo
1756        letmathspacing                      = false, -- todo
1757        resetmathspacing                    = false,
1758        setdefaultmathcodes                 = false,
1759        setmathatomrule                     = false, -- todo
1760        setmathdisplaypostpenalty           = false, -- todo
1761        setmathdisplayprepenalty            = false, -- todo
1762        setmathignore                       = false, -- todo
1763        setmathoptions                      = false, -- todo
1764        setmathpostpenalty                  = false, -- todo
1765        setmathprepenalty                   = false, -- todo
1766        setmathspacing                      = false, -- todo
1767    }
1768
1769    local s = setsyntaxfromresult(result.mathparameter)
1770
1771    s.copymathatomrule          = sequence(s_integer,s_integer)
1772    s.copymathparent            = sequence(s_integer,s_integer)
1773    s.copymathspacing           = sequence(s_integer,s_integer)
1774    s.letmathatomrule           = sequence(s_integer,s_integer,s_integer,s_integer,s_integer)
1775    s.letmathparent             = sequence(s_integer,s_integer)
1776    s.letmathspacing            = sequence(s_integer,s_integer,s_integer,s_integer,s_integer)
1777    s.resetmathspacing          = false
1778    s.setdefaultmathcodes       = false
1779    s.setmathatomrule           = sequence(s_integer,s_integer,s_mathstyle,s_integer,s_integer)
1780    s.setmathdisplaypostpenalty = sequence(s_integer,o_equal,s_integer)
1781    s.setmathdisplayprepenalty  = sequence(s_integer,o_equal,s_integer)
1782    s.setmathignore             = sequence(s_mathparameter,s_integer)
1783    s.setmathoptions            = sequence(s_integer,o_equal,s_integer)
1784    s.setmathpostpenalty        = sequence(s_integer,o_equal,s_integer)
1785    s.setmathprepenalty         = sequence(s_integer,o_equal,s_integer)
1786    s.setmathspacing            = sequence(s_integer,s_integer,s_mathstyle,s_glue)
1787
1788    syntax.mathparameter = s
1789
1790end
1791
1792do
1793
1794    result.pageproperty = newresult {
1795        deadcycles           = r_integer,
1796        insertdepth          = { s_integer, s_dimension },
1797        insertdistance       = { s_integer, s_dimension },
1798        insertheight         = { s_integer, s_dimension },
1799        insertheights        = r_dimension,
1800        insertlimit          = { s_integer, s_dimension },
1801        insertmaxdepth       = { s_integer, s_dimension },
1802        insertmultiplier     = { s_integer, s_integer },
1803        insertpenalties      = r_integer,
1804        insertpenalty        = { s_integer, s_integer },
1805        insertshrink         = { s_integer, s_dimension },
1806        insertstorage        = { s_integer, s_integer },
1807        insertstoring        = r_integer,
1808        insertstretch        = { s_integer, s_dimension },
1809        insertwidth          = { s_integer, s_dimension },
1810        mvlcurrentlyactive   = r_integer,
1811        pagedepth            = r_dimension,
1812        pageexcess           = r_dimension,
1813        pagefilllstretch     = r_dimension,
1814        pagefillstretch      = r_dimension,
1815        pagefilstretch       = r_dimension,
1816        pagefistretch        = r_dimension,
1817        pagegoal             = r_dimension,
1818        pagelastdepth        = r_dimension,
1819        pagelastfilllstretch = r_dimension,
1820        pagelastfillstretch  = r_dimension,
1821        pagelastfilstretch   = r_dimension,
1822        pagelastfistretch    = r_dimension,
1823        pagelastheight       = r_dimension,
1824        pagelastshrink       = r_dimension,
1825        pagelaststretch      = r_dimension,
1826        pageshrink           = r_dimension,
1827        pagestretch          = r_dimension,
1828        pagetotal            = r_dimension,
1829        pagevsize            = r_dimension,
1830        splitlastdepth       = r_dimension,
1831        splitlastheight      = r_dimension,
1832        splitlastshrink      = r_dimension,
1833        splitlaststretch     = r_dimension,
1834    }
1835
1836    syntax.pageproperty = setsyntaxfromresult(result.pageproperty)
1837
1838end
1839
1840local s_adjacentdemerits <const> = "<adjacentdemerits>"
1841local s_fitnessclasses   <const> = "<fitnessclasses>"
1842local s_orphanclasses    <const> = "<orphanpenalties>"
1843local s_toddlerpenalties <const> = "<toddlerpenalties>"
1844
1845syntax.specification = newsyntax {
1846    adjacentdemerits      = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1847    balancepasses         = sequence(
1848                                optional(keyword("options"),s_integer),
1849                                repeated(
1850                                    optional(keyword("next")),
1851                                    optional(keyword("quit")),
1852                                 -- optional(keyword("skip")),
1853                                    optional(sequence(keyword("adjdemerits"),s_integer)),
1854                                    optional(sequence(keyword("classes"),s_integer)),
1855                                    optional(sequence(keyword("demerits"),s_integer)),
1856                                    optional(sequence(keyword("emergencyfactor"),s_integer)),
1857                                    optional(sequence(keyword("emergencypercentage"),s_dimension)),
1858                                    optional(sequence(keyword("emergencystretch"),s_dimension)),
1859                                 -- optional(sequence(keyword("emergencyshrink"),s_dimension)),
1860                                    optional(sequence(keyword("fitnessclasses"),s_fitnessclasses)),
1861                                    optional(sequence(keyword("identifier"),s_integer)),
1862                                    optional(sequence(keyword("ifemergencystretch"),s_integer)),
1863                                    optional(sequence(keyword("iflooseness"),s_integer)),
1864                                    optional(sequence(keyword("looseness"),s_integer)),
1865                                    optional(sequence(keyword("threshold"),s_dimension)),
1866                                    optional(sequence(keyword("tolerance"),s_integer)),
1867                                    optional(sequence(keyword("pagebreakchecks"),s_integer)),
1868                                    optional(sequence(keyword("pagepenalty"),s_integer))
1869                                )
1870                            ),
1871    balanceshape          = sequence(
1872                                optional(keyword("options"),s_integer),
1873                                repeated(
1874                                    optional(keyword("next")),
1875                                    optional(sequence(keyword("index"),s_integer)),
1876                                    optional(sequence(keyword("identifier"),s_integer)),
1877                                    optional(sequence(keyword("height"),s_dimension)),
1878                                    optional(sequence(keyword("top"),s_glue)),
1879                                    optional(sequence(keyword("bottom"),s_glue)),
1880                                    optional(sequence(keyword("options"),s_integer))
1881                                )
1882                            ),
1883    brokenpenalties       = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1884    clubpenalties         = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1885    displaywidowpenalties = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1886    finalbalancepenalties = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1887    fitnessclasses        = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1888    interlinepenalties    = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1889    mathbackwardpenalties = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1890    mathforwardpenalties  = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1891    orphanpenalties       = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1892    toddlerpenalties      = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1893    parpasses             = sequence(
1894                                optional(keyword("options"),s_integer),
1895                                repeated(
1896                                    optional(keyword("next")),
1897                                    optional(keyword("quit")),
1898                                    optional(keyword("skip")),
1899                                    optional(sequence(keyword("adjdemerits"),s_integer)),
1900                                    optional(sequence(keyword("adjacentdemerits"),s_adjacentdemerits)),
1901                                    optional(sequence(keyword("adjustspacing"),s_integer)),
1902                                    optional(sequence(keyword("adjustspacingshrink"),s_integer)),
1903                                    optional(sequence(keyword("adjustspacingstep"),s_integer)),
1904                                    optional(sequence(keyword("adjustspacingstretch"),s_integer)),
1905                                 -- optional(sequence(keyword("badness"),s_integer)),
1906                                    optional(sequence(keyword("callback"),s_integer)),
1907                                    optional(sequence(keyword("classes"),s_integer)),
1908                                    optional(sequence(keyword("demerits"),s_integer)),
1909                                    optional(sequence(keyword("doubleadjdemerits"),s_integer)),
1910                                    optional(sequence(keyword("doublehyphendemerits"),s_integer)),
1911                                    optional(sequence(keyword("emergencyfactor"),s_integer)),
1912                                    optional(sequence(keyword("emergencyleftextra"),s_integer)),
1913                                    optional(sequence(keyword("emergencypercentage"),s_dimension)),
1914                                    optional(sequence(keyword("emergencyrightextra"),s_integer)),
1915                                    optional(sequence(keyword("emergencystretch"),s_dimension)),
1916                                    optional(sequence(keyword("emergencywidthextra"),s_integer)),
1917                                    optional(sequence(keyword("extrahyphenpenalty"),s_integer)),
1918                                    optional(sequence(keyword("finalhyphendemerits"),s_integer)),
1919                                    optional(sequence(keyword("fitnessclasses"),s_fitnessclasses)),
1920                                    optional(sequence(keyword("hyphenation"),s_integer)),
1921                                    optional(sequence(keyword("identifier"),s_integer)),
1922                                    optional(sequence(keyword("ifadjustspacing"),s_integer)),
1923                                    optional(sequence(keyword("ifemergencystretch"),s_integer)),
1924                                    optional(sequence(keyword("ifglue"),s_integer)),
1925                                    optional(sequence(keyword("iflooseness"),s_integer)),
1926                                    optional(sequence(keyword("ifmath"),s_integer)),
1927                                    optional(sequence(keyword("iftext"),s_integer)),
1928                                    optional(sequence(keyword("lefttwindemerits"),s_integer)),
1929                                    optional(sequence(keyword("linebreakchecks"),s_integer)),
1930                                    optional(sequence(keyword("linebreakcriterium"),s_integer)),
1931                                    optional(sequence(keyword("linebreakoptional"),s_integer)),
1932                                    optional(sequence(keyword("linepenalty"),s_integer)),
1933                                    optional(sequence(keyword("looseness"),s_integer)),
1934                                    optional(sequence(keyword("mathpenaltyfactor"),s_integer)),
1935                                    optional(sequence(keyword("orphanpenalties"),s_orphanpenalties)),
1936                                    optional(sequence(keyword("toddlerpenalties"),s_toddlerpenalties)),
1937                                    optional(sequence(keyword("righttwindemerits"),s_integer)),
1938                                    optional(sequence(keyword("threshold"),s_dimension)),
1939                                    optional(sequence(keyword("tolerance"),s_integer)),
1940                                    optional(sequence(keyword("unlessmath"),s_integer))
1941                                )
1942                            ),
1943    parpassesexception    = f_see("parpasses"),
1944    parshape              = sequence(optional(keyword("options"),s_integer),s_integer,repeated(sequence(s_dimension,s_dimension))),
1945    widowpenalties        = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1946
1947 -- dimen                 = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_integer)),
1948 -- count                 = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_dimension)),
1949 -- float                 = sequence(optional(keyword("options"),s_integer),s_integer,repeated(s_float)),
1950}
1951
1952result.specification = setdefaultresult(syntax.specification, r_integer)
1953
1954syntax.shorthanddef = newsyntax {
1955    Umathchardef     = sequence(s_cs,s_integer),
1956    Umathdictdef     = sequence(s_cs,s_integer,s_integer),
1957    attributedef     = sequence(s_cs,s_integer),
1958    chardef          = sequence(s_cs,s_integer),
1959    countdef         = sequence(s_cs,s_integer),
1960    dimendef         = sequence(s_cs,s_integer),
1961    dimensiondef     = sequence(s_cs,s_integer),
1962    floatdef         = sequence(s_cs,s_integer),
1963    fontspecdef      = sequence(s_cs,s_font),
1964    gluespecdef      = sequence(s_cs,s_integer),
1965    integerdef       = sequence(s_cs,s_integer),
1966    luadef           = sequence(s_cs,s_integer),
1967    mathchardef      = sequence(s_cs,s_integer),
1968    mugluespecdef    = sequence(s_cs,s_integer),
1969    muskipdef        = sequence(s_cs,s_integer),
1970    parameterdef     = sequence(s_cs,s_integer),
1971    positdef         = sequence(s_cs,s_integer),
1972    skipdef          = sequence(s_cs,s_integer),
1973    specificationdef = sequence(s_cs,s_specification),
1974    toksdef          = sequence(s_cs,s_integer),
1975}
1976
1977result.someitem = newresult {
1978    mathcharclass           = { s_integer, s_integer },
1979    mathcharfam             = { s_integer, s_integer },
1980    mathcharslot            = { s_integer, s_integer },
1981    badness                 = { "", s_integer   },
1982    balanceshapebottomspace = { s_integer, s_dimension },
1983    balanceshapetopspace    = { s_integer, s_dimension },
1984    balanceshapevsize       = { s_integer, s_dimension },
1985    currentgrouplevel       = { "", s_integer },
1986    currentgrouptype        = { "", s_integer },
1987    currentifbranch         = { "", s_integer },
1988    currentiflevel          = { "", s_integer },
1989    currentiftype           = { "", s_integer },
1990    currentloopiterator     = { "", s_integer },
1991    currentloopnesting      = { "", s_integer },
1992    currentstacksize        = { "", s_integer },
1993    dimexpr                 = { s_expression, s_dimension },
1994    dimexpression           = { s_expression, s_dimension },
1995    floatexpr               = { s_expression, s_float },
1996    fontcharba              = { s_fontchar, s_dimension },
1997    fontchardp              = { s_fontchar, s_dimension },
1998    fontcharht              = { s_fontchar, s_dimension },
1999    fontcharic              = { s_fontchar, s_dimension },
2000    fontcharta              = { s_fontchar, s_dimension },
2001    fontcharwd              = { s_fontchar, s_dimension },
2002    fontid                  = { s_font, s_integer },
2003    fontmathcontrol         = { s_font, s_integer },
2004    fontspecid              = { s_font, s_integer },
2005    fontspecifiedsize       = { s_font, s_integer },
2006    fontspecscale           = { s_font, s_integer },
2007    fontspecslant           = { s_font, s_integer },
2008    fontspecxscale          = { s_font, s_integer },
2009    fontspecyscale          = { s_font, s_integer },
2010    fontspecweight          = { s_font, s_integer },
2011    fonttextcontrol         = { s_font, s_integer },
2012    glueexpr                = { s_expression, s_glue },
2013    glueshrink              = { s_glue, s_dimension },
2014    glueshrinkorder         = { s_glue, s_dimension },
2015    gluestretch             = { s_glue, s_integer},
2016    gluestretchorder        = { s_glue, s_integer},
2017    gluetomu                = { s_glue, s_glue },
2018    glyphxscaled            = { "", s_integer },
2019    glyphyscaled            = { "", s_integer },
2020    indexofcharacter        = { s_integer, s_integer },
2021    indexofregister         = { s_integer, s_integer },
2022    inputlineno             = { "",s_integer },
2023    insertprogress          = { s_integer, s_dimension },-- check
2024    lastarguments           = { "", s_integer },
2025    lastatomclass           = { "", s_integer },
2026    lastboundary            = { "", s_integer },
2027    lastchkdimension        = { "", s_dimension },
2028    lastchknumber           = { "", s_integer },
2029    lastkern                = { "", s_dimension },
2030    lastleftclass           = { "", s_integer },
2031    lastloopiterator        = { "", s_integer },
2032    lastnodesubtype         = { "", s_integer },
2033    lastnodetype            = { "", s_integer },
2034    lastpageextra           = { "", s_dimension },
2035    lastparcontext          = { "", s_integer },
2036    lastpartrigger          = { "", s_integer },
2037    lastpenalty             = { "", s_integer },
2038    lastrightclass          = { "", s_integer },
2039    lastskip                = { "", s_glue },
2040    leftmarginkern          = { "", s_dimension }, -- check
2041    luametatexmajorversion  = { "", s_integer },
2042    luametatexminorversion  = { "", s_integer },
2043    luametatexrelease       = { "", s_integer },
2044    luatexrevision          = { "", s_integer },
2045    luatexversion           = { "", s_integer },
2046    mathatomglue            = { "", s_glue },
2047    mathmainstyle           = { "", s_integer },
2048    mathparentstyle         = { "", s_integer },
2049    mathscale               = { "", s_integer },
2050    mathstackstyle          = { "", s_integer },
2051    mathstyle               = { "", s_integer },
2052    mathstylefontid         = { "", s_integer },
2053    muexpr                  = { s_expression, s_muglue },
2054    mutoglue                = { s_muglue, s_glue },
2055    nestedloopiterator      = { "", s_integer },
2056    numericscale            = { s_number, s_integer },
2057    numericscaled           = { s_number, s_integer },
2058    numexpr                 = { s_expression, s_integer },
2059    numexpression           = { s_expression, s_integer },
2060    overshoot               = { "", s_dimension },
2061    parametercount          = { "", s_integer },
2062    parameterindex          = { "", s_integer },
2063    parshapedimen           = { s_integer, s_dimension },
2064    parshapeindent          = { s_integer, s_dimension },
2065    parshapelength          = { "", s_dimension },
2066    parshapewidth           = { "", s_dimension },
2067    previousloopiterator    = { "", s_integer },
2068    rightmarginkern         = { "", s_dimension }, -- check
2069    scaledemwidth           = { s_font, s_dimension },
2070    scaledexheight          = { s_font, s_dimension },
2071    scaledextraspace        = { s_font, s_dimension },
2072    scaledfontcharba        = { s_fontchar, s_dimension },
2073    scaledfontchardp        = { s_fontchar, s_dimension },
2074    scaledfontcharht        = { s_fontchar, s_dimension },
2075    scaledfontcharic        = { s_fontchar, s_dimension },
2076    scaledfontcharta        = { s_fontchar, s_dimension },
2077    scaledfontcharwd        = { s_fontchar, s_dimension },
2078    scaledinterwordshrink   = { s_font, s_dimension },
2079    scaledinterwordspace    = { s_font, s_dimension },
2080    scaledinterwordstretch  = { s_font, s_dimension },
2081    scaledmathaxis          = { s_mathstyle, s_dimension },
2082    scaledmathemwidth       = { s_mathstyle, s_dimension },
2083    scaledmathexheight      = { s_mathstyle, s_dimension },
2084    scaledslantperpoint     = { s_font, s_dimension },
2085}
2086
2087syntax.someitem = setsyntaxfromresult(result.someitem)
2088
2089syntax.the = newsyntax {
2090    detokenize                  = s_tokens,
2091    expandeddetokenize          = s_tokens,
2092    protecteddetokenize         = s_tokens,
2093    protectedexpandeddetokenize = s_tokens,
2094    the                         = s_dimension,
2095    thewithoutunit              = s_quantity,
2096    unexpanded                  = s_tokens,
2097}
2098
2099syntax.unhbox = newsyntax {
2100    unhbox  = s_integer,
2101    unhcopy = s_integer,
2102    unhpack = s_integer,
2103}
2104
2105syntax.unvbox = newsyntax {
2106    copysplitdiscards = false,
2107    insertunbox       = s_integer,
2108    insertuncopy      = s_integer,
2109    pagediscards      = false,
2110    splitdiscards     = false,
2111    unvbox            = s_integer,
2112    unvcopy           = s_integer,
2113    unvpack           = s_integer,
2114}
2115
2116syntax.vadjust = newsyntax {
2117    vadjust = sequence(
2118        optional(keyword("pre")),
2119        optional(keyword("post")),
2120        optional(keyword("baseline")),
2121        optional(keyword("before")),
2122        optional(sequence(keyword("index"),s_integer)),
2123        optional(keyword("after")),
2124        optional(sequence(keyword("attr"),s_integer,s_integer)),
2125        optional(sequence(keyword("depth"),choice(keyword("after"),keyword("before"),keyword("check"),keyword("last")))),
2126        s_tokens
2127    )
2128}
2129
2130syntax.valign = newsyntax {
2131    valign = syntax.halign.halign
2132}
2133
2134syntax.vcenter = newsyntax {
2135    vcenter = syntax.makebox.dbox
2136}
2137
2138syntax.vmove = newsyntax {
2139    raise = syntax.hmove.moveleft,
2140    lower = syntax.hmove.moveright,
2141}
2142
2143syntax.vrule = newsyntax {
2144    novrule      = normal_rule,
2145    srule        = strut_rule,
2146    virtualvrule = normal_rule,
2147    vrule        = normal_rule,
2148}
2149
2150syntax.vskip = newsyntax {
2151   vfil    = false,
2152   vfill   = false,
2153   vfilneg = false,
2154   vskip   = syntax.hskip.hskip,
2155   vss     = false,
2156}
2157
2158syntax.xray = newsyntax {
2159    show          = s_token,
2160    showbox       = s_boxreference,
2161    showcodestack = false,
2162    showgroups    = false,
2163    showifs       = false,
2164    showlists     = false,
2165    showstack     = false,
2166    showthe       = s_quantity,
2167    showtokens    = s_tokens,
2168}
2169
2170-- so far
2171
2172local striplines = utilities.strings.striplines
2173
2174for cmd, chrs in next, syntax do
2175    for chr, str in next, chrs do
2176        if not str then
2177            chrs[chr] = ""
2178        elseif str ~= "" then
2179            chrs[chr] = striplines(str,"prune and to space")
2180        end
2181    end
2182end
2183
2184for cmd, chrs in next, result do
2185    for chr, str in next, chrs do
2186        if str then
2187            local s1 = str[1]
2188            local s2 = str[2]
2189            if not s1 then
2190                str[1] = ""
2191            elseif s1 ~= "" then
2192                str[1] = striplines(s1,"prune and to space")
2193            end
2194            if not s2 then
2195                str[2] = ""
2196            elseif s2 ~= "" then
2197                str[2] = striplines(s2,"prune and to space")
2198            end
2199        end
2200    end
2201end
2202
2203-- end of syntax specification
2204
2205do
2206
2207    local P   = lpeg.P
2208    local R   = lpeg.R
2209    local Cmt = lpeg.Cmt
2210
2211    local space   = lpeg.patterns.whitespace
2212    local unspace = lpeg.patterns.whitespace^0
2213    local word    = R("az","AZ")^1
2214    local utfchar = lpeg.patterns.utf8character
2215
2216    local p_enhance = (
2217                  P("[") * unspace / "" / context.SyntaxLeftBracket
2218      + unspace * P("]")           / "" / context.SyntaxRightBracket
2219      +           P("{") * unspace / "" / context.SyntaxLeftBrace
2220      + unspace * P("}")           / "" / context.SyntaxRightBrace
2221      +           P("(") * unspace / "" / context.SyntaxLeftParenthesis
2222      + unspace * P(")")           / "" / context.SyntaxRightParenthesis
2223      + unspace * P("|") * unspace / "" / context.SyntaxBar
2224      + P("character")   / context.SyntaxCharacter
2225      + P("token")       / context.SyntaxToken
2226      + P("tokens")      / context.SyntaxTokens
2227      + P("integer")     / context.SyntaxInteger
2228      + P("quantity")    / context.SyntaxQuantity
2229      + P("preamble")    / context.SyntaxPreamble
2230      + P("dimension")   / context.SyntaxDimension
2231      + P("glue")        / context.SyntaxGlue
2232      + P("muglue")      / context.SyntaxMuglue
2233      + P("float")       / context.SyntaxFloat
2234      + P("font")        / context.SyntaxFont
2235      + P("mathstyle")   / context.SyntaxMathstyle
2236      + P("tokenlist")   / context.SyntaxTokenlist
2237      + P("box")         / context.SyntaxBox
2238      + P("rule")        / context.SyntaxRule
2239      + P("toks")        / context.SyntaxToks
2240      + P("float")       / context.SyntaxFloat
2241      + P("cs")          / context.SyntaxCs
2242      + P("conditional") / context.SyntaxConditional
2243      + P("\\") * (word  / context.tex)
2244      + space^1          / context.space
2245      + utfchar          / context.type
2246
2247    )^1
2248
2249    local compact = false
2250    local compact = true
2251
2252    local cmd = setmetatableindex("table")
2253    local lst = { }
2254    local cat = { }
2255    local org = { }
2256
2257    for i=1,#primitives do
2258        local l = primitives[i]
2259        local n = gsub(commandnames[l[1]],"_","")
2260        local p = l[3]
2261        local t = {
2262            syntax[n][p] or false,
2263            result[n][p] or false,
2264        }
2265        cmd[n][p] = t
2266        lst[p]    = t
2267        cat[p]    = category[n]
2268        org[p]    = l[4]
2269    end
2270    local tag = { }
2271    for k, v in next, origins do
2272        tag[k] = sub(v,1,1)
2273    end
2274
2275    moduledata.engine.data = {
2276        cmd = cmd,
2277        lst = lst,
2278        org = org,
2279        cat = cat,
2280    }
2281
2282    local function specification(k,v,done)
2283        local s = v[1]
2284        local r = v[2]
2285        local d = done[s]
2286        context.formatted.startPrimitive("%s \\tex{%s}",tag[commandhash[k][4]],k)
2287        if s and s ~= "" then
2288            if d then
2289                context(" see \\tex{%s}",done[s])
2290                r = false
2291            else
2292                lpegmatch(p_enhance,s)
2293                if compact and count(s," ") > 2 then
2294                    done[s] = k
2295                end
2296            end
2297        else
2298            context.allowbreak(false)
2299        end
2300        if r and r ~= "" then
2301            if s and s ~= "" then
2302                context["break"](false)
2303            end
2304            context.strut()
2305            if r[1] and r[1] ~= "" then
2306                context.llap("> ")
2307                lpegmatch(p_enhance,r[1])
2308                context(" : ")
2309            else
2310                context.llap(": ")
2311            end
2312            lpegmatch(p_enhance,r[2])
2313        else
2314            context.allowbreak(false)
2315        end
2316        context.stopPrimitive()
2317    end
2318
2319    function moduledata.engine.specification(k)
2320        local v = lst[k]
2321        if v then
2322            context.startpacked()
2323            specification(k,v,{})
2324            context.stoppacked()
2325        else
2326            print("no command " .. k)
2327        end
2328    end
2329
2330    function moduledata.engine.allspecifications()
2331        for k, v in sortedhash(cmd) do
2332            local done = { }
2333            context.startSyntax { title = k }
2334                for k, v in sortedhash(v) do
2335                    specification(k,v,done)
2336                end
2337            context.stopSyntax()
2338
2339            table.save("s-system-syntax-check.lua",{
2340                syntax   = syntax,
2341                result   = result,
2342                keywords = keywords,
2343                compares = compares,
2344            })
2345
2346        end
2347    end
2348
2349end
2350
2351do
2352
2353    local context = context
2354
2355    local ctx_NC, ctx_NR = context.NC, context.NR
2356    local ctx_starttabulate, ctx_stoptabulate = context.starttabulate, context.stoptabulate
2357
2358    function moduledata.engine.codes(name,...)
2359        local t = (type(name) == "table" and name) or tex[name]
2360        if type(t) == "function" then
2361            t = t(...)
2362        end
2363        if t then
2364            local l = { }
2365            for k, v in table.sortedhash(t) do
2366                if tonumber(k) then
2367                    l[#l+1] = k
2368                end
2369            end
2370            local m = l[#l]
2371            local f = (m > 0x00FFFFFF and "0x%08X") or (m > 0x000FFFF and "0x%06X") or (m > 0x00FF and "0x%04X") or "0x%02X"
2372            ctx_starttabulate { "|lT|l|" }
2373            for i=1,#l do
2374                local li = l[i]
2375                ctx_NC() context(f,li)
2376                ctx_NC() context(t[li])
2377                ctx_NC() ctx_NR()
2378            end
2379            ctx_stoptabulate()
2380        else
2381            context("there is no function tex.%s",name)
2382        end
2383    end
2384
2385    function moduledata.mplib.codes(what)
2386        local f = mplib[what]
2387        if f then
2388            local t = f()
2389            if t then
2390                ctx_starttabulate { "|lT|l|" }
2391                if #t > 0 then
2392                    for i=0,#t do
2393                        ctx_NC() context(i)
2394                        ctx_NC() context(t[i])
2395                        ctx_NC() ctx_NR()
2396                    end
2397                else
2398                    for k, v in table.sortedhash(t) do
2399                        ctx_NC() context(k)
2400                        ctx_NC() context(v)
2401                        ctx_NC() ctx_NR()
2402                    end
2403                end
2404                ctx_stoptabulate()
2405            end
2406        else
2407            context("there is no function mplib.%s",what)
2408        end
2409    end
2410
2411    function moduledata.pdfe.codes(what)
2412        local f = pdfe[what]
2413        if f then
2414            local t = f()
2415            if t then
2416                ctx_starttabulate { "|lT|l|" }
2417                for k, v in table.sortedhash(t) do
2418                    ctx_NC() context(k)
2419                    ctx_NC() context(v)
2420                    ctx_NC() ctx_NR()
2421                end
2422                ctx_stoptabulate()
2423            end
2424        else
2425            context("there is no function pdfe.%s",what)
2426        end
2427    end
2428
2429    function moduledata.node.codes(what,...)
2430        local f = node[what]
2431        if f then
2432            local t = f(...)
2433            if t then
2434                ctx_starttabulate { "|lT|l|" }
2435                for k, v in table.sortedhash(t) do
2436                    ctx_NC() context(k)
2437                    ctx_NC() context(v)
2438                    ctx_NC() ctx_NR()
2439                end
2440                ctx_stoptabulate()
2441            end
2442        else
2443            context("there is no function node.%s",what)
2444        end
2445    end
2446
2447end
2448