@tabnas/abnf 0.4.21 → 0.4.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abnf.d.ts +1 -1
- package/dist/abnf.js +1 -1
- package/dist/translate.js +450 -44
- package/dist/translate.js.map +1 -1
- package/package.json +1 -1
- package/src/abnf.ts +1 -1
- package/src/translate.ts +450 -44
package/dist/abnf.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export { VERSION, abnf, abnfConvert, parseAbnf, emitGrammarSpec, eliminateLeftRe
|
|
|
6
6
|
export type { AbnfConvertOptions, AbnfCompileOptions, ActionsMap };
|
|
7
7
|
export { translate } from './translate';
|
|
8
8
|
export type { TranslationPart, TranslationParts } from './translate';
|
|
9
|
-
declare const VERSION = "0.4.
|
|
9
|
+
declare const VERSION = "0.4.22";
|
package/dist/abnf.js
CHANGED
|
@@ -38,6 +38,6 @@ Object.defineProperty(exports, "translate", { enumerable: true, get: function ()
|
|
|
38
38
|
// VERSION is this package's version. It MUST equal package.json "version":
|
|
39
39
|
// the release orchestrator rewrites both, and the version test fails the
|
|
40
40
|
// build if they drift. Mirrors `const VERSION` in go/abnf.go.
|
|
41
|
-
const VERSION = '0.4.
|
|
41
|
+
const VERSION = '0.4.22';
|
|
42
42
|
exports.VERSION = VERSION;
|
|
43
43
|
//# sourceMappingURL=abnf.js.map
|
package/dist/translate.js
CHANGED
|
@@ -43,12 +43,13 @@ const TRANSLATION = Object.freeze({
|
|
|
43
43
|
"Where the compiler reordered a rule's alternatives to tell them apart (a longer lookahead ahead of a shorter one that begins with the same character, a keyword ahead of a character class that can take it), the alternatives that push a helper of the compiler's are put back in the order its numbers record, and the others are written in the compiled order: the rule compiles back the same, and the spec compiled back can differ in the order of the alternates other rules build through it, in the numbers of the compiler's helpers and in the order of its tokens, which is the order the lexer tries two tokens a place expects, so where a keyword and a class that can take it trade places the grammar compiled back accepts what the spec refused (start = ident / \\"if\\" ident with ident = %x61-7A: the spec refuses ifx, and the text compiles back to one that accepts it).",
|
|
44
44
|
"A left recursion that ran through another rule (P = Q, Q = P \\"+\\" / NR) is written as the compiler rewrote it, with the leading reference that closed the cycle left in place, and compiles back to another spec, since the compiler now substitutes that reference.",
|
|
45
45
|
"The start rule is written first, as ABNF's start rule is its first; a spec whose start rule was not its first rule compiles back with that rule moved first.",
|
|
46
|
-
"Terminals are written in RFC 5234's forms: a literal as a quoted string (with %s where it matches exactly and holds a letter) or, where a quoted string cannot hold it, as a numeric value of its code points, a range as %x and its ends, and a rule the compiler made a token of (CR = %x0D, referenced as CR) as that rule, after the others.",
|
|
46
|
+
"Terminals are written in RFC 5234's forms: a literal as a quoted string (with %s where it matches exactly and holds a letter) or, where a quoted string cannot hold it, as a numeric value of its code points, a range as %x and its ends, the class of every code point (GBNF's dot) as %x0-10FFFF, and a rule the compiler made a token of (CR = %x0D, referenced as CR) as that rule, after the others.",
|
|
47
47
|
"A rule the compiler made a token of, whose name is one the compiler could give its literal by itself (B = \\"b\\", or any name of capitals, digits and underscores where the literal holds a character past ASCII), cannot be told from that literal and is written as the literal: it compiles back with the token later in the token table, or under the name the literal gives it.",
|
|
48
48
|
"Repetitions are written in RFC 5234's forms, *A, 1*A, m*nA, [ A ] for an option over a group and 0*1A for an option over anything else; a repetition of a repetition, which another notation can write and RFC 5234 cannot, is put in a group of its own and compiles back with one more group.",
|
|
49
49
|
"An empty alternative, which RFC 5234 has no syntax for, is written as nothing between its slashes, which the compiler reads as one; in a rule whose alternatives the compiler emits as its open alternates, where it puts the empty one last wherever it stood, it is written first.",
|
|
50
50
|
"A spec compiled from another notation compiles back under ABNF's own settings: the group tag on every alternate, and lexer options the other notation adds (GBNF's exact lexing), are ABNF's, and a class of several members, which RFC 5234 cannot write, is written as the alternation of its members, each range a range and each character a string or a range of one, and compiles back as that alternation.",
|
|
51
|
-
"
|
|
51
|
+
"The tree builders every compiled grammar carries (@node$, @capture$, @bubble$ and @fold$, with their k settings) and its marks are not written, since the compiler makes them again from the rules: a spec whose builders or marks are others compiles back with the compiler's own, and recognises what it recognised.",
|
|
52
|
+
"A spec the render cannot write as ABNF is refused with TARGET_VALUE_UNREPRESENTABLE, naming what it met: an action (a value annotation's builders, a user action, the probe dispatcher of an optional prefix), a condition or a counter other than a repetition's, an error generator or an alternate modifier, a function reference where a rule or a count is due, a set of tokens at one place, a removal, a clear or the form that edits a rule already installed, a token no ABNF terminal matches (a negated class, a class holding a character past ASCII alone, a class whose flags change what it matches (no u on a class that is negated, reaches past U+FFFF or holds every code point, or u on one that holds a surrogate), a pattern that is neither one class nor an escaped literal, a case-sensitive literal holding a letter and a character no quoted string holds, a case-insensitive literal holding a character past ASCII and no ASCII letter, whose numeric value would match one case alone, a character past U+FFFF), a token set whose tokens are not the class its name gives, a rule with no alternate to open with, a sequence's step with more alternates than a step, a rule the compiler lifted to a token whose name another rule holds, a start that is not the start wrapper every grammar text compiles to (one open alternate that matches nothing and pushes a rule, closed by the end of the source alone), a rule name ABNF cannot spell, the empty name among them, a repetition bounded past what the compiler numbers, a repetition of no copies, whose item the spec does not keep, or a spec that gives its match tokens' order as a list of its own (Go's tokenOrder), whose rules' order, which ranks the tokens, is lost."
|
|
52
53
|
]
|
|
53
54
|
}
|
|
54
55
|
}
|
|
@@ -72,17 +73,20 @@ const TRANSLATION = Object.freeze({
|
|
|
72
73
|
; reads the compiler's shapes back into the notation:
|
|
73
74
|
;
|
|
74
75
|
; - A rule the author wrote is a rule of the spec that the spec's
|
|
75
|
-
; \`meta.provenance\` does not name
|
|
76
|
-
; compiler
|
|
77
|
-
;
|
|
78
|
-
;
|
|
79
|
-
;
|
|
80
|
-
;
|
|
81
|
-
;
|
|
82
|
-
;
|
|
83
|
-
;
|
|
84
|
-
;
|
|
85
|
-
;
|
|
76
|
+
; \`meta.provenance\` does not name (a spec without it is read by the
|
|
77
|
+
; names the compiler gives its rules, a helper's only where it has
|
|
78
|
+
; the shape of its kind too, and the start wrapper by its shape);
|
|
79
|
+
; every rule it names is the compiler's: a repetition's, an
|
|
80
|
+
; option's or a group's helper (\`_gen<n>_star_...\`, \`_plus_\`, \`_opt_\`,
|
|
81
|
+
; \`_rep_\`, \`_group\`), a sequence's chain steps (\`$alt<i>\`,
|
|
82
|
+
; \`$step<j>\`), a left-factored tail (\`$fact<k>\`) and the start
|
|
83
|
+
; wrapper. A helper is written where it is referenced, as the
|
|
84
|
+
; construct it compiles: a repeat loop (the replace loop every \`*A\`
|
|
85
|
+
; compiles to, its entry \`{c: {n.rep: 0}, r: <self>}\`) as \`*A\`, a plus
|
|
86
|
+
; as \`1*A\`, an option over a group as \`[ ... ]\` and over anything else
|
|
87
|
+
; as \`0*1A\`, a counted repetition as \`m*nA\` (its nested optionals
|
|
88
|
+
; counted), a group as \`( ... )\`. A factored tail is expanded back
|
|
89
|
+
; into the alternatives it was factored from, which the compiler
|
|
86
90
|
; factors again, and alternatives that were each a group, which the
|
|
87
91
|
; compiler factored into the first, are read back as the groups they
|
|
88
92
|
; were.
|
|
@@ -102,32 +106,48 @@ const TRANSLATION = Object.freeze({
|
|
|
102
106
|
; by one same tail, still stand together.
|
|
103
107
|
; - A token is written as the terminal it matches: a fixed token as a
|
|
104
108
|
; quoted string, \`%s"..."\` where it holds a letter, a case-folding
|
|
105
|
-
; match token as a quoted string, a range as \`%x<lo>-<hi>\` (a token
|
|
106
|
-
; the compiler laid over a contested range read back from its
|
|
107
|
-
;
|
|
108
|
-
;
|
|
109
|
-
;
|
|
110
|
-
;
|
|
111
|
-
;
|
|
109
|
+
; match token as a quoted string, a range as \`%x<lo>-<hi>\` (a token
|
|
110
|
+
; set the compiler laid over a contested range read back from its
|
|
111
|
+
; name, once its tokens are found to be that range), \`[\\s\\S]\` (GBNF's
|
|
112
|
+
; \`.\`) as \`%x0-10FFFF\`, and the engine's \`#TX\`, \`#NR\`, \`#ST\` and \`#VL\`
|
|
113
|
+
; by their names. A string a quoted string cannot hold is written as a
|
|
114
|
+
; numeric value, \`%x<hex>.<hex>\`, which the compiler reads as
|
|
115
|
+
; case-insensitive where it holds a letter of ASCII and as exact where
|
|
116
|
+
; it holds none: a case-folding string past ASCII with no such letter,
|
|
117
|
+
; whose numeric value would match one case alone, is refused. A token
|
|
118
|
+
; named for a rule the
|
|
119
|
+
; compiler lifted to it (\`CR = %x0D\` becomes the token \`#CR\`) is
|
|
120
|
+
; written as that rule, after the others, and referenced by name.
|
|
112
121
|
; - An RFC 5234 core rule (ALPHA, DIGIT, ...) in the spec is not written,
|
|
113
122
|
; since the compiler adds it again wherever it is referenced, and a
|
|
114
123
|
; leading reference to one is written back as any other is.
|
|
115
124
|
;
|
|
116
125
|
; What a rule cannot be read back to is refused with
|
|
117
|
-
; TARGET_VALUE_UNREPRESENTABLE, naming the rule: an action other than
|
|
118
|
-
; tree builders every compiled grammar carries (a value annotation's
|
|
126
|
+
; TARGET_VALUE_UNREPRESENTABLE, naming the rule: an action other than
|
|
127
|
+
; the tree builders every compiled grammar carries (a value annotation's
|
|
119
128
|
; builders, a user action, the probe dispatcher's), a condition or a
|
|
120
129
|
; counter other than a repeat loop's, an error generator or an alternate
|
|
121
130
|
; modifier (\`e\`, \`h\`), a function reference where a rule or a count is
|
|
122
131
|
; due, a set of tokens at one place, the form that edits a rule already
|
|
123
132
|
; installed (\`{alts, inject}\`), a removal, and a token no ABNF terminal
|
|
124
|
-
; matches (a negated class, a class holding a character past ASCII
|
|
125
|
-
; a class whose flags change what it matches, a pattern that is
|
|
126
|
-
; one class nor an escaped literal). A
|
|
127
|
-
;
|
|
128
|
-
;
|
|
129
|
-
;
|
|
130
|
-
;
|
|
133
|
+
; matches (a negated class, a class holding a character past ASCII
|
|
134
|
+
; alone, a class whose flags change what it matches, a pattern that is
|
|
135
|
+
; neither one class nor an escaped literal). A token set whose tokens
|
|
136
|
+
; are not the class its name gives, a rule with no alternate to open
|
|
137
|
+
; with, a sequence's step with more alternates than a step, and a rule
|
|
138
|
+
; the compiler lifted to a token whose name another rule holds are
|
|
139
|
+
; refused too. A spec serialized by Go, which writes its rules in name
|
|
140
|
+
; order and its match tokens' order as a list of its own
|
|
141
|
+
; (\`options.match.tokenOrder\`), is refused when that list holds two
|
|
142
|
+
; tokens or more: the rules' order, which ranks the tokens (the order
|
|
143
|
+
; the lexer tries two tokens a place expects), is lost. The tree
|
|
144
|
+
; builders and the marks are not written: the compiler makes them again
|
|
145
|
+
; from the rules.
|
|
146
|
+
; A spec whose start is not the start wrapper every grammar text
|
|
147
|
+
; compiles to (one open alternate that matches nothing and pushes a
|
|
148
|
+
; rule, closed by the end of the source alone) is refused as well: its
|
|
149
|
+
; text would compile back inside such a wrapper, whose close lets the
|
|
150
|
+
; end of the source come after what the lexer skips.
|
|
131
151
|
;
|
|
132
152
|
; A spec compiled from another notation is written as far as ABNF can say
|
|
133
153
|
; it: a class of several members (GBNF's and EBNF's \`[a-zA-Z_]\`) as the
|
|
@@ -344,9 +364,154 @@ def abnf-made [cx name]
|
|
|
344
364
|
case :string true
|
|
345
365
|
case _ false
|
|
346
366
|
case _
|
|
347
|
-
match (abnf-
|
|
348
|
-
case true
|
|
349
|
-
case false
|
|
367
|
+
match (abnf-some (abnf-rest (split "$" name)))
|
|
368
|
+
case true (abnf-split-name name)
|
|
369
|
+
case false
|
|
370
|
+
match (abnf-gen-kind name)
|
|
371
|
+
case ""
|
|
372
|
+
match (abnf-same name (get :start cx))
|
|
373
|
+
case true (abnf-wrapper (abnf-rule cx name))
|
|
374
|
+
case false false
|
|
375
|
+
case k (abnf-helper-shape cx name k)
|
|
376
|
+
|
|
377
|
+
; The kind of helper a name gives, as the compiler names the helpers it
|
|
378
|
+
; makes, \`_gen<n>_<kind>...\` with the kind a repetition's, an option's or
|
|
379
|
+
; a group's (\`_gen3_star_x\`, \`_gen4_group\`), or "" for any other name: a
|
|
380
|
+
; rule the author wrote may begin with \`_gen\` too (\`_general\`).
|
|
381
|
+
def abnf-gen-kind [name]
|
|
382
|
+
match (abnf-starts "_gen" name)
|
|
383
|
+
case false ""
|
|
384
|
+
case true
|
|
385
|
+
let [parts (split "_" (abnf-after "_gen" name))]
|
|
386
|
+
match (count parts)
|
|
387
|
+
case 1 ""
|
|
388
|
+
case _
|
|
389
|
+
match (match (abnf-digits (abnf-at parts 0)) (case true (abnf-among (abnf-at parts 1) ["star" "plus" "opt" "rep" "group"])) (case false false))
|
|
390
|
+
case true (abnf-at parts 1)
|
|
391
|
+
case false ""
|
|
392
|
+
|
|
393
|
+
; Whether a name is one the compiler gives a rule it splits off another,
|
|
394
|
+
; every part after a \`$\` one of its own: a dispatcher's alternative
|
|
395
|
+
; (\`$alt<i>\`), a chain's step (\`$step<j>\`), a left-factored tail
|
|
396
|
+
; (\`$fact<k>\`), a probe dispatcher (\`$pd<i>\`) and its parts (\`$probe\`,
|
|
397
|
+
; \`$with\`, \`$no\`, numbered where the name was taken).
|
|
398
|
+
def abnf-split-name [name]
|
|
399
|
+
abnf-none (filter (fn [p] (abnf-not (abnf-split-part p))) (abnf-rest (split "$" name)))
|
|
400
|
+
|
|
401
|
+
def abnf-split-part [p]
|
|
402
|
+
abnf-some (filter (fn [k] (abnf-split-fits k p)) ["alt" "step" "fact" "pd" "probe" "with" "no"])
|
|
403
|
+
|
|
404
|
+
def abnf-split-fits [k p]
|
|
405
|
+
match (abnf-starts k p)
|
|
406
|
+
case false false
|
|
407
|
+
case true
|
|
408
|
+
match (abnf-after k p)
|
|
409
|
+
case "" (abnf-among k ["probe" "with" "no"])
|
|
410
|
+
case rest (abnf-digits rest)
|
|
411
|
+
|
|
412
|
+
; A rule named as the compiler names a helper, in a spec that names no
|
|
413
|
+
; provenance, is the compiler's where it has the shape the compiler gives
|
|
414
|
+
; that kind, and the author's otherwise: a repetition's loop has its
|
|
415
|
+
; guarded entry (\`{c: {n.rep: 0}, r: <self>}\`); a plus is its item and the
|
|
416
|
+
; loop after it; an option one element and the empty alternative; a
|
|
417
|
+
; counted repetition copies of one element, and the option or the loop
|
|
418
|
+
; after them; a group any alternatives.
|
|
419
|
+
def abnf-helper-shape [cx name k]
|
|
420
|
+
match k
|
|
421
|
+
case "group" true
|
|
422
|
+
case "star" (abnf-some (filter (fn [alt] (abnf-loop-entry name alt)) (abnf-open (abnf-rule cx name))))
|
|
423
|
+
case _
|
|
424
|
+
let [alts (abnf-raw-alts cx name)]
|
|
425
|
+
match k
|
|
426
|
+
case "plus" (abnf-plus-shape alts)
|
|
427
|
+
case "opt" (abnf-opt-shape alts)
|
|
428
|
+
case _ (abnf-rep-shape alts)
|
|
429
|
+
|
|
430
|
+
def abnf-loop-entry [name alt]
|
|
431
|
+
match (abnf-same (abnf-r alt) name)
|
|
432
|
+
case false false
|
|
433
|
+
case true
|
|
434
|
+
let [c (get "c" alt)]
|
|
435
|
+
match (kind c)
|
|
436
|
+
case :record (abnf-loop-value c "n.rep" [0])
|
|
437
|
+
case _ false
|
|
438
|
+
|
|
439
|
+
def abnf-plus-shape [alts]
|
|
440
|
+
match (count alts)
|
|
441
|
+
case 1
|
|
442
|
+
let [seq (abnf-vec (abnf-at alts 0))]
|
|
443
|
+
match (count seq)
|
|
444
|
+
case 2 (abnf-same (abnf-helper-ref (abnf-at seq 1)) "star")
|
|
445
|
+
case _ false
|
|
446
|
+
case _ false
|
|
447
|
+
|
|
448
|
+
def abnf-opt-shape [alts]
|
|
449
|
+
match (count alts)
|
|
450
|
+
case 2
|
|
451
|
+
let [counts (map count alts)]
|
|
452
|
+
match (abnf-among "0" (map abnf-num counts))
|
|
453
|
+
case true (abnf-among "1" (map abnf-num counts))
|
|
454
|
+
case false false
|
|
455
|
+
case _ false
|
|
456
|
+
|
|
457
|
+
def abnf-rep-shape [alts]
|
|
458
|
+
match (count alts)
|
|
459
|
+
case 1
|
|
460
|
+
let [seq (abnf-vec (abnf-at alts 0))]
|
|
461
|
+
match (count seq)
|
|
462
|
+
case 0 true
|
|
463
|
+
case _
|
|
464
|
+
let [lead (match (abnf-among (abnf-helper-ref (top seq)) ["star" "opt"]) (case true (pop seq)) (case false seq))]
|
|
465
|
+
let [keys (map abnf-el-name lead)]
|
|
466
|
+
abnf-none (filter (fn [key] (match key (case "" true) (case _ (abnf-not (abnf-same key (abnf-at keys 0)))))) keys)
|
|
467
|
+
case _ false
|
|
468
|
+
|
|
469
|
+
; The kind of helper an element references by name, or "".
|
|
470
|
+
def abnf-helper-ref [el]
|
|
471
|
+
match (get :k el)
|
|
472
|
+
case :ref (abnf-gen-kind (get :name el))
|
|
473
|
+
case _ ""
|
|
474
|
+
|
|
475
|
+
; A token or a reference by its name, any other element "".
|
|
476
|
+
def abnf-el-name [el]
|
|
477
|
+
match (get :k el)
|
|
478
|
+
case :tok (string-join "" ["#" (get :name el)])
|
|
479
|
+
case :ref (string-join "" ["@" (get :name el)])
|
|
480
|
+
case _ ""
|
|
481
|
+
|
|
482
|
+
; The start wrapper the compiler adds, which \`options.rule.start\` names:
|
|
483
|
+
; one open alternate that consumes nothing and pushes the grammar's start
|
|
484
|
+
; rule, and the end of the source, and nothing else, to close it.
|
|
485
|
+
def abnf-wrapper [r]
|
|
486
|
+
let [o (abnf-open r)]
|
|
487
|
+
match (count o)
|
|
488
|
+
case 1
|
|
489
|
+
let [a (abnf-at o 0)]
|
|
490
|
+
match (match (abnf-some (abnf-s a)) (case true false) (case false (abnf-full (abnf-p a))))
|
|
491
|
+
case false false
|
|
492
|
+
case true
|
|
493
|
+
let [c (abnf-close r)]
|
|
494
|
+
match (count c)
|
|
495
|
+
case 0 false
|
|
496
|
+
case _ (abnf-none (filter (fn [x] (abnf-not (abnf-wrapper-end x))) c))
|
|
497
|
+
case _ false
|
|
498
|
+
|
|
499
|
+
; A close alternate that matches the end of the source and goes nowhere.
|
|
500
|
+
def abnf-wrapper-end [alt]
|
|
501
|
+
match (abnf-same (string-join " " (abnf-s alt)) "#ZZ")
|
|
502
|
+
case false false
|
|
503
|
+
case true (abnf-empty (abnf-target alt))
|
|
504
|
+
|
|
505
|
+
; Every grammar text compiles to a start wrapper around its start rule,
|
|
506
|
+
; and the wrapper's close lets the end of the source come after what the
|
|
507
|
+
; lexer skips (\`ab \` where the grammar is \`ab\`). So the rule
|
|
508
|
+
; \`options.rule.start\` names must be that wrapper: a spec that starts at
|
|
509
|
+
; another rule, or at a wrapper without its close, would come back
|
|
510
|
+
; accepting what it refuses.
|
|
511
|
+
def abnf-check-start [cx]
|
|
512
|
+
match (abnf-wrapper (abnf-rule cx (get :start cx)))
|
|
513
|
+
case true true
|
|
514
|
+
case false (abnf-fail (string-join "" ["the start rule " (get :start cx) " is not the start wrapper every grammar text compiles to (one open alternate that matches nothing and pushes a rule, closed by the end of the source alone)"]))
|
|
350
515
|
|
|
351
516
|
; The kind the tree builders give a rule the author wrote: "user", or
|
|
352
517
|
; "core" for an RFC 5234 core rule the compiler added.
|
|
@@ -493,7 +658,9 @@ def abnf-check-rule [cx name]
|
|
|
493
658
|
match (kind r)
|
|
494
659
|
case :record
|
|
495
660
|
let [phases (count (map (fn [phase] (abnf-check-phase name phase (get phase r))) ["open" "close"]))]
|
|
496
|
-
|
|
661
|
+
match (count (abnf-open r))
|
|
662
|
+
case 0 (abnf-fail (string-join "" ["rule " name " has no alternate to open with, which no grammar text writes"]))
|
|
663
|
+
case _ (count (map (fn [alt] (abnf-check-alt cx name alt)) (abnf-cat (abnf-open r) (abnf-close r))))
|
|
497
664
|
case :null (abnf-fail (string-join "" ["rule " name " is removed, which is not written"]))
|
|
498
665
|
case _ (abnf-fail (string-join "" ["rule " name " is not a rule's alternates, which is not written"]))
|
|
499
666
|
|
|
@@ -515,7 +682,9 @@ def abnf-check [spec cx]
|
|
|
515
682
|
case true (abnf-fail "it clears the grammar it is installed on, which is not written")
|
|
516
683
|
case _
|
|
517
684
|
let [order (abnf-check-order spec)]
|
|
518
|
-
|
|
685
|
+
let [start (abnf-check-start cx)]
|
|
686
|
+
let [rules (count (map (fn [name] (abnf-check-rule cx name)) (keys (get :rules cx))))]
|
|
687
|
+
abnf-check-sets cx (abnf-used cx)
|
|
519
688
|
|
|
520
689
|
; ---- tokens
|
|
521
690
|
|
|
@@ -554,9 +723,9 @@ def abnf-match-token [t m]
|
|
|
554
723
|
match (abnf-class-pattern body)
|
|
555
724
|
case false (abnf-fail (string-join "" ["the token " t " is the pattern " m ", which is not one class the render reads, and no ABNF terminal matches it"]))
|
|
556
725
|
case true
|
|
557
|
-
match (abnf-
|
|
726
|
+
match (abnf-flags-fit body flags)
|
|
558
727
|
case true (abnf-class body flags)
|
|
559
|
-
case false (abnf-fail (string-join "" ["the token " t " is the class " m ", whose flags (" flags ") change what it matches, and no ABNF terminal matches it"]))
|
|
728
|
+
case false (abnf-fail (string-join "" ["the token " t " is the class " m ", whose flags (" (match flags (case "" "none") (case _ flags)) ") change what it matches, and no ABNF terminal matches it"]))
|
|
560
729
|
case false
|
|
561
730
|
match flags
|
|
562
731
|
case "i"
|
|
@@ -689,6 +858,193 @@ def abnf-trim-end-once [s]
|
|
|
689
858
|
case true (abnf-before "_" s)
|
|
690
859
|
case false s
|
|
691
860
|
|
|
861
|
+
; ---- code points and the ranges a class holds
|
|
862
|
+
|
|
863
|
+
; A code point, from its one to six hexadecimal digits in either case, as
|
|
864
|
+
; three numbers, its bytes from the highest, each the place of its two
|
|
865
|
+
; digits among \`abnf-hex-pairs\`: code points are ordered as these are.
|
|
866
|
+
def abnf-cp [h]
|
|
867
|
+
let [x (abnf-six (abnf-hex-upper h))]
|
|
868
|
+
let [high (abnf-pair-start x)]
|
|
869
|
+
let [rest (abnf-after high x)]
|
|
870
|
+
vector (abnf-pair-index high) (abnf-pair-index (abnf-pair-start rest)) (abnf-pair-index (abnf-pair-end rest))
|
|
871
|
+
|
|
872
|
+
def abnf-six [h]
|
|
873
|
+
string-join "" [(match (length h) (case 1 "00000") (case 2 "0000") (case 3 "000") (case 4 "00") (case 5 "0") (case _ "")) h]
|
|
874
|
+
|
|
875
|
+
def abnf-pair-start [x]
|
|
876
|
+
abnf-at (filter (fn [p] (abnf-starts p x)) abnf-hex-pairs) 0
|
|
877
|
+
|
|
878
|
+
def abnf-pair-end [x]
|
|
879
|
+
abnf-at (filter (fn [p] (abnf-ends p x)) abnf-hex-pairs) 0
|
|
880
|
+
|
|
881
|
+
def abnf-pair-index [p]
|
|
882
|
+
abnf-at (filter (fn [i] (abnf-same (abnf-at abnf-hex-pairs i) p)) (indices abnf-hex-pairs)) 0
|
|
883
|
+
|
|
884
|
+
def abnf-cp-order [a b]
|
|
885
|
+
match (compare (abnf-at a 0) (abnf-at b 0))
|
|
886
|
+
case :equal
|
|
887
|
+
match (compare (abnf-at a 1) (abnf-at b 1))
|
|
888
|
+
case :equal (compare (abnf-at a 2) (abnf-at b 2))
|
|
889
|
+
case other other
|
|
890
|
+
case other other
|
|
891
|
+
|
|
892
|
+
def abnf-cp-before [a b]
|
|
893
|
+
match (abnf-cp-order a b)
|
|
894
|
+
case :less true
|
|
895
|
+
case _ false
|
|
896
|
+
|
|
897
|
+
def abnf-cp-is [a b]
|
|
898
|
+
match (abnf-cp-order a b)
|
|
899
|
+
case :equal true
|
|
900
|
+
case _ false
|
|
901
|
+
|
|
902
|
+
; The code point after one: its low byte one more, carried into the bytes
|
|
903
|
+
; above it.
|
|
904
|
+
def abnf-cp-next [c]
|
|
905
|
+
match (abnf-at c 2)
|
|
906
|
+
case 255
|
|
907
|
+
match (abnf-at c 1)
|
|
908
|
+
case 255 (vector (abnf-plus (abnf-at c 0) 1) 0 0)
|
|
909
|
+
case _ (vector (abnf-at c 0) (abnf-plus (abnf-at c 1) 1) 0)
|
|
910
|
+
case _ (vector (abnf-at c 0) (abnf-at c 1) (abnf-plus (abnf-at c 2) 1))
|
|
911
|
+
|
|
912
|
+
def abnf-cp-max [cps]
|
|
913
|
+
abnf-at (filter (fn [c] (abnf-none (filter (fn [d] (abnf-cp-before c d)) cps))) cps) 0
|
|
914
|
+
|
|
915
|
+
def abnf-span [lo hi]
|
|
916
|
+
record
|
|
917
|
+
entry :lo lo
|
|
918
|
+
entry :hi hi
|
|
919
|
+
|
|
920
|
+
; The members of a class's pattern, read as \`abnf-class-pattern\` admits
|
|
921
|
+
; them: each a range, from its low end's digits to its high end's (a
|
|
922
|
+
; character alone is a range of one); \`[\\s\\S]\` every code point. A
|
|
923
|
+
; negated class's are the ones it excludes.
|
|
924
|
+
def abnf-class-hex-spans [body]
|
|
925
|
+
match body
|
|
926
|
+
case "[\\\\s\\\\S]" [(abnf-span "0" "10FFFF")]
|
|
927
|
+
case _
|
|
928
|
+
let [inner (abnf-before "]" (abnf-after "[" body))]
|
|
929
|
+
let [pieces (abnf-rest (split "\\\\u" (match (abnf-starts "^" inner) (case true (abnf-after "^" inner)) (case false inner))))]
|
|
930
|
+
let [lows (map (fn [p] (abnf-ends "-" p)) pieces)]
|
|
931
|
+
let [ends (abnf-cat [false] lows)]
|
|
932
|
+
map
|
|
933
|
+
fn [i]
|
|
934
|
+
let [lo (abnf-piece-hex (abnf-at pieces i))]
|
|
935
|
+
match (abnf-at lows i)
|
|
936
|
+
case true (abnf-span lo (abnf-piece-hex (abnf-at pieces (abnf-plus i 1))))
|
|
937
|
+
case false (abnf-span lo lo)
|
|
938
|
+
filter (fn [i] (abnf-not (abnf-at ends i))) (indices pieces)
|
|
939
|
+
|
|
940
|
+
def abnf-piece-hex [p]
|
|
941
|
+
let [core (match (abnf-ends "-" p) (case true (abnf-before "-" p)) (case false p))]
|
|
942
|
+
match (abnf-starts "{" core)
|
|
943
|
+
case true (abnf-before "}" (abnf-after "{" core))
|
|
944
|
+
case false core
|
|
945
|
+
|
|
946
|
+
def abnf-class-spans [body]
|
|
947
|
+
map (fn [s] (abnf-span (abnf-cp (get :lo s)) (abnf-cp (get :hi s)))) (abnf-class-hex-spans body)
|
|
948
|
+
|
|
949
|
+
; Ranges sorted by their low ends and merged where they overlap or meet:
|
|
950
|
+
; two lists of ranges hold the same code points when these are the same.
|
|
951
|
+
def abnf-spans-merged [spans]
|
|
952
|
+
let [sorted (abnf-spans-sorted spans)]
|
|
953
|
+
let [starts (filter (fn [i] (abnf-none (filter (fn [j] (match (abnf-less j i) (case true (abnf-not (abnf-cp-before (abnf-cp-next (get :hi (abnf-at sorted j))) (get :lo (abnf-at sorted i))))) (case false false))) (indices sorted)))) (indices sorted))]
|
|
954
|
+
map (fn [k] (abnf-block-span sorted starts k)) (indices starts)
|
|
955
|
+
|
|
956
|
+
def abnf-block-span [sorted starts k]
|
|
957
|
+
let [from (abnf-at starts k)]
|
|
958
|
+
let [members (filter (fn [i] (match (abnf-less i from) (case true false) (case false (abnf-before-start starts k i)))) (indices sorted))]
|
|
959
|
+
abnf-span (get :lo (abnf-at sorted from)) (abnf-cp-max (map (fn [i] (get :hi (abnf-at sorted i))) members))
|
|
960
|
+
|
|
961
|
+
def abnf-before-start [starts k i]
|
|
962
|
+
match (abnf-less (abnf-plus k 1) (count starts))
|
|
963
|
+
case true (abnf-less i (abnf-at starts (abnf-plus k 1)))
|
|
964
|
+
case false true
|
|
965
|
+
|
|
966
|
+
def abnf-spans-sorted [spans]
|
|
967
|
+
let [ranks (map (fn [i] (count (filter (fn [j] (match (abnf-cp-order (get :lo (abnf-at spans j)) (get :lo (abnf-at spans i))) (case :less true) (case :equal (abnf-less j i)) (case _ false))) (indices spans)))) (indices spans))]
|
|
968
|
+
map (fn [k] (abnf-at spans (abnf-at (filter (fn [i] (match (compare (abnf-at ranks i) k) (case :equal true) (case _ false))) (indices spans)) 0))) (indices spans)
|
|
969
|
+
|
|
970
|
+
def abnf-spans-same [a b]
|
|
971
|
+
match (compare (count a) (count b))
|
|
972
|
+
case :equal (abnf-none (filter (fn [i] (match (abnf-cp-is (get :lo (abnf-at a i)) (get :lo (abnf-at b i))) (case true (abnf-not (abnf-cp-is (get :hi (abnf-at a i)) (get :hi (abnf-at b i))))) (case false true))) (indices a)))
|
|
973
|
+
case _ false
|
|
974
|
+
|
|
975
|
+
; Whether two lists of ranges hold every code point between them, each
|
|
976
|
+
; once: a negated class's ranges and the ranges it matches.
|
|
977
|
+
def abnf-spans-tile [a b]
|
|
978
|
+
let [all (abnf-spans-sorted (abnf-cat (abnf-spans-merged a) (abnf-spans-merged b)))]
|
|
979
|
+
match (count all)
|
|
980
|
+
case 0 false
|
|
981
|
+
case _
|
|
982
|
+
match (match (abnf-cp-is (get :lo (abnf-at all 0)) (abnf-cp "0")) (case true (abnf-cp-is (get :hi (top all)) (abnf-cp "10FFFF"))) (case false false))
|
|
983
|
+
case false false
|
|
984
|
+
case true
|
|
985
|
+
let [nexts (abnf-rest all)]
|
|
986
|
+
abnf-none (filter (fn [i] (abnf-not (abnf-cp-is (get :lo (abnf-at nexts i)) (abnf-cp-next (get :hi (abnf-at all i)))))) (indices nexts))
|
|
987
|
+
|
|
988
|
+
; Whether a class's flags are the ones it is matched with once its text is
|
|
989
|
+
; written and compiled back. Every compiler here gives \`u\` to a class that
|
|
990
|
+
; is negated, holds a character past U+FFFF or is \`[\\s\\S]\`, and to no
|
|
991
|
+
; other. Without \`u\` such a class matches one UTF-16 code unit, half of a
|
|
992
|
+
; character past U+FFFF, and with it one code point. A class of other
|
|
993
|
+
; characters matches the same either way, unless it holds a surrogate,
|
|
994
|
+
; which \`u\` matches only where it stands alone.
|
|
995
|
+
def abnf-flags-fit [body flags]
|
|
996
|
+
match (abnf-wants-u body)
|
|
997
|
+
case true (abnf-same flags "u")
|
|
998
|
+
case false
|
|
999
|
+
match (abnf-holds-surrogate body)
|
|
1000
|
+
case true (abnf-empty flags)
|
|
1001
|
+
case false (abnf-among flags ["" "u"])
|
|
1002
|
+
|
|
1003
|
+
def abnf-wants-u [body]
|
|
1004
|
+
match body
|
|
1005
|
+
case "[\\\\s\\\\S]" true
|
|
1006
|
+
case _
|
|
1007
|
+
match (abnf-starts "[^" body)
|
|
1008
|
+
case true true
|
|
1009
|
+
case false (abnf-some (abnf-rest (split "\\\\u{" body)))
|
|
1010
|
+
|
|
1011
|
+
; A class none of whose members is past U+FFFF holds a surrogate where a
|
|
1012
|
+
; range's low end is not above U+DFFF and its high end not below U+D800.
|
|
1013
|
+
def abnf-holds-surrogate [body]
|
|
1014
|
+
abnf-some (filter (fn [s] (match (abnf-hex-from (get :lo s) ["E" "F"]) (case true false) (case false (abnf-hex-from (get :hi s) ["D8" "D9" "DA" "DB" "DC" "DD" "DE" "DF" "E" "F"])))) (abnf-class-hex-spans body))
|
|
1015
|
+
|
|
1016
|
+
def abnf-hex-from [h prefixes]
|
|
1017
|
+
let [x (abnf-hex-upper h)]
|
|
1018
|
+
match (length x)
|
|
1019
|
+
case 4 (abnf-some (filter (fn [p] (abnf-starts p x)) prefixes))
|
|
1020
|
+
case _ false
|
|
1021
|
+
|
|
1022
|
+
; A token set is the class its name gives when the tokens it lays over
|
|
1023
|
+
; that class are the class: their ranges, merged, are the class's ranges,
|
|
1024
|
+
; or, for a negated class, every code point the class does not exclude.
|
|
1025
|
+
; The compiler lays a contested class over the atoms of a partition, each
|
|
1026
|
+
; a token of its own, and names the set for the class; the render writes
|
|
1027
|
+
; the class the name gives, so a set whose tokens match anything else is
|
|
1028
|
+
; refused.
|
|
1029
|
+
def abnf-check-sets [cx used]
|
|
1030
|
+
count (map (fn [k] (abnf-check-set cx (string-join "" ["#" k]))) (filter (fn [k] (match (abnf-starts "RX_" k) (case true (abnf-some (abnf-rest (split (string-join "" [" #" k " "]) used)))) (case false false))) (keys (get :sets cx))))
|
|
1031
|
+
|
|
1032
|
+
def abnf-check-set [cx t]
|
|
1033
|
+
let [cls (abnf-set-token t)]
|
|
1034
|
+
let [pat (get :pat cls)]
|
|
1035
|
+
let [spans (abnf-flat (map (fn [m] (abnf-member-spans cx t m)) (abnf-vec (get-path (as-path [(abnf-bare t)]) (get :sets cx)))))]
|
|
1036
|
+
let [own (abnf-class-spans pat)]
|
|
1037
|
+
match (match (abnf-starts "[^" pat) (case true (abnf-spans-tile own spans)) (case false (abnf-spans-same (abnf-spans-merged own) (abnf-spans-merged spans))))
|
|
1038
|
+
case true true
|
|
1039
|
+
case false (abnf-fail (string-join "" ["the token set " t " lays tokens over its class " pat " that match other characters than the class does, and the render writes the class the set's name gives"]))
|
|
1040
|
+
|
|
1041
|
+
def abnf-member-spans [cx t m]
|
|
1042
|
+
let [src (match (kind m) (case :string (abnf-str (get-path (as-path [m]) (get :match cx)))) (case _ ""))]
|
|
1043
|
+
let [body (abnf-after "^" (string-join "/" (pop (abnf-rest (split "/" src)))))]
|
|
1044
|
+
match (match (abnf-starts "@" src) (case true (match (abnf-class-pattern body) (case true (match (abnf-starts "[^" body) (case true false) (case false (abnf-flags-fit body (top (split "/" src)))))) (case false false))) (case false false))
|
|
1045
|
+
case true (abnf-class-spans body)
|
|
1046
|
+
case false (abnf-fail (string-join "" ["the token set " t " holds " (abnf-str m) ", which is not one class the render reads"]))
|
|
1047
|
+
|
|
692
1048
|
def abnf-engine-token [t]
|
|
693
1049
|
match t
|
|
694
1050
|
case "#TX" (record (entry :k :engine) (entry :name "TX"))
|
|
@@ -752,11 +1108,23 @@ def abnf-entry-key [alt]
|
|
|
752
1108
|
; the empty alternative, or a guard that ends it on what may follow; two
|
|
753
1109
|
; or more bare ones (\`a ::= | \`) are as many empty alternatives.
|
|
754
1110
|
def abnf-simple-alts [r]
|
|
755
|
-
let [alts (map abnf-entry-els (abnf-unique abnf-entry-key (abnf-open r)))]
|
|
1111
|
+
let [alts (abnf-flat (map (fn [alt] (map (fn [i] (abnf-entry-els alt)) (indices (abnf-ones (abnf-copies (abnf-open r) alt))))) (abnf-unique abnf-entry-key (abnf-open r))))]
|
|
756
1112
|
let [bare (count (filter abnf-bare-empty (abnf-open r)))]
|
|
757
1113
|
let [empties (match (abnf-some (filter abnf-none alts)) (case false []) (case true (map (fn [i] []) (indices (abnf-ones (match (abnf-less bare 2) (case true 1) (case false bare)))))))]
|
|
758
1114
|
abnf-cat empties (abnf-number-order (filter abnf-some alts))
|
|
759
1115
|
|
|
1116
|
+
; How many times an alternative stands among the open alternates: the
|
|
1117
|
+
; lookahead copies a dispatch makes of one alternative consume and push the
|
|
1118
|
+
; same and look ahead at different tokens, and are one; alternates alike
|
|
1119
|
+
; in everything are as many alternatives as there are of them.
|
|
1120
|
+
def abnf-copies [open alt]
|
|
1121
|
+
let [group (filter (fn [a] (abnf-same (abnf-entry-key a) (abnf-entry-key alt))) open)]
|
|
1122
|
+
let [counts (map (fn [a] (count (filter (fn [b] (abnf-same (abnf-whole-key b) (abnf-whole-key a))) group))) group)]
|
|
1123
|
+
abnf-at (filter (fn [c] (abnf-none (filter (fn [d] (abnf-less c d)) counts))) counts) 0
|
|
1124
|
+
|
|
1125
|
+
def abnf-whole-key [alt]
|
|
1126
|
+
string-join "" [(string-join " " (abnf-s alt)) "|" (abnf-num (abnf-b alt)) "|" (abnf-target alt)]
|
|
1127
|
+
|
|
760
1128
|
def abnf-bare-empty [alt]
|
|
761
1129
|
match (abnf-some (abnf-s alt))
|
|
762
1130
|
case true false
|
|
@@ -805,7 +1173,7 @@ def abnf-filled [alts]
|
|
|
805
1173
|
; The steps of a chain, each a segment: the tokens its open alternate
|
|
806
1174
|
; consumes and the rule it pushes, the next step named in its close.
|
|
807
1175
|
def abnf-chain-walk [self cx name depth acc]
|
|
808
|
-
let [r (abnf-rule cx name)]
|
|
1176
|
+
let [r (abnf-chain-step name (abnf-rule cx name))]
|
|
809
1177
|
let [els (abnf-cat acc (abnf-entry-els (abnf-at (abnf-open r) 0)))]
|
|
810
1178
|
match (count (abnf-close r))
|
|
811
1179
|
case 0 els
|
|
@@ -902,6 +1270,15 @@ def abnf-raw-alts [cx name]
|
|
|
902
1270
|
case "" (abnf-simple-alts r)
|
|
903
1271
|
case _ (vector (abnf-chain cx name))
|
|
904
1272
|
|
|
1273
|
+
; A step of a sequence's chain, as the compiler makes one: one open
|
|
1274
|
+
; alternate, a segment of the sequence, and at most one close alternate,
|
|
1275
|
+
; which names the next step. A rule that replaces itself in its close and
|
|
1276
|
+
; has more alternates than that is no chain the render reads back.
|
|
1277
|
+
def abnf-chain-step [name r]
|
|
1278
|
+
match (match (count (abnf-open r)) (case 1 (abnf-less (count (abnf-close r)) 2)) (case _ false))
|
|
1279
|
+
case true r
|
|
1280
|
+
case false (abnf-fail (string-join "" ["rule " name " replaces itself in its close as a sequence's step does, and has more alternates than a step, which is not read back"]))
|
|
1281
|
+
|
|
905
1282
|
; ---- the compiler's helpers, read back
|
|
906
1283
|
|
|
907
1284
|
; The kind of a helper the compiler named: \`_gen<n>_<kind>...\`.
|
|
@@ -1338,8 +1715,12 @@ def abnf-unsub-at [cx alts best accepted covers i]
|
|
|
1338
1715
|
|
|
1339
1716
|
; A literal: a quoted string where it can hold the text (\`%s\` before it
|
|
1340
1717
|
; when the match is exact and the text holds a letter), and otherwise a
|
|
1341
|
-
; numeric value, \`%x\` and each character's code point, which
|
|
1342
|
-
; as a case-insensitive string
|
|
1718
|
+
; numeric value, \`%x\` and each character's code point, which tabnas-abnf
|
|
1719
|
+
; reads as a case-insensitive string where it holds a letter of ASCII,
|
|
1720
|
+
; with the folding a case-insensitive pattern has, and as an exact one
|
|
1721
|
+
; where it holds none. So a case-insensitive literal holding a character
|
|
1722
|
+
; past ASCII, which may have cases, and no letter of ASCII is refused: its
|
|
1723
|
+
; numeric value would match the one case it spells.
|
|
1343
1724
|
def abnf-lit-text [text cs]
|
|
1344
1725
|
match text
|
|
1345
1726
|
case "" "\\"\\""
|
|
@@ -1358,7 +1739,10 @@ def abnf-lit-text [text cs]
|
|
|
1358
1739
|
match (abnf-has-letter text)
|
|
1359
1740
|
case true (abnf-fail (string-join "" ["the case-sensitive literal " (quoted text) " holds a character a quoted string cannot hold, and a numeric value matches case-insensitively"]))
|
|
1360
1741
|
case false (string-join "" ["%x" (string-join "." (abnf-codes text))])
|
|
1361
|
-
case false
|
|
1742
|
+
case false
|
|
1743
|
+
match (match (abnf-has-letter text) (case true true) (case false (chars-within [[0 127] [65536 1114111]] text)))
|
|
1744
|
+
case true (string-join "" ["%x" (string-join "." (abnf-codes text))])
|
|
1745
|
+
case false (abnf-fail (string-join "" ["the case-insensitive literal " (quoted text) " holds a character past ASCII that may have cases and no ASCII letter, and a numeric value without a letter matches exactly"]))
|
|
1362
1746
|
|
|
1363
1747
|
; A code point of a class's pattern, \`\\uXXXX\` or \`\\u{X...}\`, as ABNF's
|
|
1364
1748
|
; hexadecimal digits.
|
|
@@ -1378,8 +1762,14 @@ def abnf-escape-hex [e]
|
|
|
1378
1762
|
; class of several members, which another notation writes, as the
|
|
1379
1763
|
; alternation of its members, each range a range and each character a
|
|
1380
1764
|
; string that matches it exactly, or a range of one where a string cannot
|
|
1381
|
-
; hold it
|
|
1765
|
+
; hold it; \`[\\s\\S]\` (GBNF's \`.\`) as the range of every code point. A
|
|
1766
|
+
; negated class has no ABNF form.
|
|
1382
1767
|
def abnf-class-text [pat flags]
|
|
1768
|
+
match pat
|
|
1769
|
+
case "[\\\\s\\\\S]" "%x0-10FFFF"
|
|
1770
|
+
case _ (abnf-range-text pat)
|
|
1771
|
+
|
|
1772
|
+
def abnf-range-text [pat]
|
|
1383
1773
|
let [body (abnf-before "]" (abnf-after "[" pat))]
|
|
1384
1774
|
match (abnf-starts "^" body)
|
|
1385
1775
|
case true (abnf-fail (string-join "" ["the class " pat " is negated, which ABNF has no form for"]))
|
|
@@ -1582,8 +1972,24 @@ def abnf-lifted-production [cx t]
|
|
|
1582
1972
|
let [info (abnf-token cx t)]
|
|
1583
1973
|
string-join "" [(abnf-ref-text (abnf-bare t)) " = " (abnf-lit-text (get :text info) (get :cs info))]
|
|
1584
1974
|
|
|
1975
|
+
; A rule the compiler lifted to a token is written under the token's name,
|
|
1976
|
+
; which no rule of the spec may hold already: two productions of one name
|
|
1977
|
+
; are one rule.
|
|
1978
|
+
def abnf-check-lifted [cx lifted]
|
|
1979
|
+
map
|
|
1980
|
+
fn [t]
|
|
1981
|
+
match (abnf-has cx (abnf-bare t))
|
|
1982
|
+
case true (abnf-fail (string-join "" ["the token " t " is written as a rule named " (abnf-bare t) ", the name of another rule the spec holds"]))
|
|
1983
|
+
case false t
|
|
1984
|
+
lifted
|
|
1985
|
+
|
|
1986
|
+
; The grammar's start rule: the one the start wrapper pushes, or the rule
|
|
1987
|
+
; \`options.rule.start\` names where it is no wrapper.
|
|
1585
1988
|
def abnf-start-rule [cx]
|
|
1586
|
-
|
|
1989
|
+
let [r (abnf-rule cx (get :start cx))]
|
|
1990
|
+
match (abnf-wrapper r)
|
|
1991
|
+
case true (abnf-p (abnf-at (abnf-open r) 0))
|
|
1992
|
+
case false (get :start cx)
|
|
1587
1993
|
|
|
1588
1994
|
def abnf-file [spec]
|
|
1589
1995
|
let [cx (abnf-context spec)]
|
|
@@ -1593,7 +1999,7 @@ def abnf-file [spec]
|
|
|
1593
1999
|
let [ordered (abnf-cat [start] (filter (fn [n] (abnf-not (abnf-same n start))) names))]
|
|
1594
2000
|
let [used (abnf-used cx)]
|
|
1595
2001
|
let [tokens (abnf-cat (keys (get :fixed cx)) (keys (get :match cx)))]
|
|
1596
|
-
let [lifted (filter (fn [t] (abnf-lifted cx used t)) tokens)]
|
|
2002
|
+
let [lifted (abnf-check-lifted cx (filter (fn [t] (abnf-lifted cx used t)) tokens))]
|
|
1597
2003
|
let [cands (abnf-candidates cx (abnf-cat ordered (abnf-direct-core cx)))]
|
|
1598
2004
|
string-join ""
|
|
1599
2005
|
vector
|