From a6001b32cf805c4e72e05adc37ee60272a600bf1 Mon Sep 17 00:00:00 2001 From: Ryo Nihei Date: Sat, 5 Nov 2022 16:52:37 +0900 Subject: Remove anonymous symbol system Remove unimportant features to tidy up the specification. --- README.md | 64 ++++++++++-------- driver/parser_test.go | 68 ++++++++++++++------ driver/semantic_action.go | 6 +- driver/syntax_error_test.go | 47 ++++++-------- grammar/grammar.go | 123 ++++++----------------------------- grammar/grammar_test.go | 46 ++++--------- grammar/parsing_table.go | 7 -- spec/grammar/description.go | 1 - spec/grammar/parser.go | 2 +- spec/grammar/parser_test.go | 132 ++++++++++++++++++++++++++------------ spec/test/parser.go | 6 +- spec/test/tree-report.json | 2 +- spec/test/tree_semantic_action.go | 6 +- 13 files changed, 233 insertions(+), 277 deletions(-) diff --git a/README.md b/README.md index 568190f..006781e 100644 --- a/README.md +++ b/README.md @@ -304,14 +304,12 @@ Alternative: ... ``` -An element an alternative contains is a terminal symbol, a non-terminal symbol, or a string literal. Unlike string literals, patterns cannot be contained in alternatives. - -You can define terminal symbols in the same grammar as non-terminal symbols. +An element an alternative contains is a terminal symbol or a non-terminal symbol. If a production rule satisfies all of the following conditions, it is considered to define a terminal symbol. -* A production rule has only one alternative. -* the alternative has only one pattern or string literal. +* A rule has only one alternative. +* The alternative has only one pattern or string literal. Fragment: @@ -367,15 +365,21 @@ Consider a grammar that accepts comma-separated list of integers. You can avoid #name example; list - : '[' elems ']' #ast elems... + : l_bracket elems r_bracket #ast elems... ; elems - : elems ',' int #ast elems... int + : elems comma int #ast elems... int | int ; ws #skip - : "[\u{0009}\u{0020}]+"; + : "[\u{0009}\u{0020}]+"; +l_bracket + : '['; +r_bracket + : ']'; +comma + : ','; int : "0|[1-9][0-9]*"; ``` @@ -398,11 +402,15 @@ Consider a grammar that accepts ternary-if expression (` ? ";" -├─ statement +│ └─ semi_colon ";" +├─ eq_expr │ ├─ error -│ └─ ";" -└─ statement +│ └─ semi_colon ";" +└─ eq_expr ├─ name "x" └─ int "1" +1:2: unexpected token: ';' (semi_colon): expected: eq +1:7: unexpected token: ';' (semi_colon): expected: int ``` diff --git a/driver/parser_test.go b/driver/parser_test.go index dd58dd5..da4f714 100644 --- a/driver/parser_test.go +++ b/driver/parser_test.go @@ -186,7 +186,9 @@ bar : bar_text | ; -bar_text: "bar"; + +bar_text + : "bar"; `, src: `bar`, cst: nonTermNode("s", @@ -399,8 +401,10 @@ white_space #skip s : tagline ; -tagline: "\f{words} IS OUT THERE."; -fragment words: "[A-Za-z\u{0020}]+"; +tagline + : "\f{words} IS OUT THERE."; +fragment words + : "[A-Za-z\u{0020}]+"; `, src: `THE TRUTH IS OUT THERE.`, }, @@ -410,15 +414,21 @@ fragment words: "[A-Za-z\u{0020}]+"; #name test; list - : '[' elems ']' #ast elems... + : l_bracket elems r_bracket #ast elems... ; elems - : elems ',' id #ast elems... id + : elems comma id #ast elems... id | id ; whitespace #skip : "\u{0020}+"; +l_bracket + : '['; +r_bracket + : ']'; +comma + : ','; id : "[A-Za-z]+"; `, @@ -453,10 +463,12 @@ s : a #ast a... ; a - : a ',' foo #ast a... foo + : a comma foo #ast a... foo | foo ; +comma + : ','; foo : 'foo'; `, @@ -473,12 +485,14 @@ foo #name test; s - : a ';' #ast a... + : a semi_colon #ast a... ; - a : ; + +semi_colon + : ';'; `, src: `;`, ast: nonTermNode("s"), @@ -497,9 +511,13 @@ expr | expr@lhs sub expr@rhs #ast sub lhs rhs | num ; -add: '+'; -sub: '-'; -num: "0|[1-9][0-9]*"; + +add + : '+'; +sub + : '-'; +num + : "0|[1-9][0-9]*"; `, src: `1+2-3`, ast: nonTermNode("expr", @@ -524,9 +542,11 @@ num: "0|[1-9][0-9]*"; #name test; s - : foo@x ';' #ast foo + : foo@x semi_colon #ast foo ; +semi_colon + : ';'; foo : 'foo'; `, @@ -648,12 +668,14 @@ div #name test; s - : id id id ';' - | error ';' + : id id id semi_colon + | error semi_colon ; ws #skip : "[\u{0009}\u{0020}]+"; +semi_colon + : ';'; id : "[A-Za-z_]+"; `, @@ -665,10 +687,12 @@ id #name test; s - : foo ';' - | error ';' #ast error + : foo semi_colon + | error semi_colon #ast error ; +semi_colon + : ';'; foo : 'foo'; `, @@ -684,10 +708,12 @@ foo #name test; s - : foo ';' - | error@e ';' #ast e + : foo semi_colon + | error@e semi_colon #ast e ; +semi_colon + : ';'; foo : 'foo'; `, @@ -707,12 +733,14 @@ seq | elem ; elem - : id id id ';' - | error ';' #recover + : id id id semi_colon + | error semi_colon #recover ; ws #skip : "[\u{0009}\u{0020}]+"; +semi_colon + : ';'; id : "[A-Za-z_]+"; `, diff --git a/driver/semantic_action.go b/driver/semantic_action.go index 54d3291..7e5a773 100644 --- a/driver/semantic_action.go +++ b/driver/semantic_action.go @@ -340,11 +340,7 @@ func printTree(w io.Writer, node *Node, ruledLine string, childRuledLinePrefix s case NodeTypeError: fmt.Fprintf(w, "%v%v\n", ruledLine, node.KindName) case NodeTypeTerminal: - if node.KindName == "" { - fmt.Fprintf(w, "%v %v\n", ruledLine, strconv.Quote(node.Text)) - } else { - fmt.Fprintf(w, "%v%v %v\n", ruledLine, node.KindName, strconv.Quote(node.Text)) - } + fmt.Fprintf(w, "%v%v %v\n", ruledLine, node.KindName, strconv.Quote(node.Text)) case NodeTypeNonTerminal: fmt.Fprintf(w, "%v%v\n", ruledLine, node.KindName) diff --git a/driver/syntax_error_test.go b/driver/syntax_error_test.go index ada1fb0..683e355 100644 --- a/driver/syntax_error_test.go +++ b/driver/syntax_error_test.go @@ -26,7 +26,8 @@ s : foo ; -foo: 'foo'; +foo + : 'foo'; `, src: `bar`, synErrCount: 1, @@ -37,9 +38,9 @@ foo: 'foo'; #name test; seq - : seq elem ';' - | elem ';' - | error ';' #recover + : seq elem semi_colon + | elem semi_colon + | error semi_colon #recover ; elem : a b c @@ -47,6 +48,8 @@ elem ws #skip : "[\u{0009}\u{0020}]+"; +semi_colon + : ';'; a : 'a'; b @@ -63,9 +66,9 @@ c #name test; seq - : seq elem ';' - | elem ';' - | error ';' #recover + : seq elem semi_colon + | elem semi_colon + | error semi_colon #recover ; elem : a b c @@ -73,6 +76,8 @@ elem ws #skip : "[\u{0009}\u{0020}]+"; +semi_colon + : ';'; a : 'a'; b @@ -91,9 +96,9 @@ c #name test; seq - : seq elem ';' - | elem ';' - | error '*' '*' ';' + : seq elem semi_colon + | elem semi_colon + | error star star semi_colon ; elem : a b c @@ -101,6 +106,10 @@ elem ws #skip : "[\u{0009}\u{0020}]+"; +semi_colon + : ';'; +star + : '*'; a : 'a'; b @@ -241,24 +250,6 @@ foo "", }, }, - { - caption: "when an anonymous symbol is expected, an expected symbol list contains an auto-generated name with the prefix `x_`", - specSrc: ` -#name test; - -s - : foo 'bar' - ; - -foo - : 'foo'; -`, - src: `foobaz`, - cause: `baz`, - expected: []string{ - "x_1", - }, - }, } for i, tt := range tests { t.Run(fmt.Sprintf("#%v", i), func(t *testing.T) { diff --git a/grammar/grammar.go b/grammar/grammar.go index e2f9ba0..16126ec 100644 --- a/grammar/grammar.go +++ b/grammar/grammar.go @@ -84,7 +84,6 @@ type Grammar struct { name string lexSpec *mlspec.LexSpec skipLexKinds []mlspec.LexKindName - sym2AnonPat map[symbol]string productionSet *productionSet augmentedStartSymbol symbol errorSymbol symbol @@ -211,7 +210,6 @@ func (b *GrammarBuilder) Build() (*Grammar, error) { name: specName, lexSpec: symTabAndLexSpec.lexSpec, skipLexKinds: symTabAndLexSpec.skip, - sym2AnonPat: symTabAndLexSpec.sym2AnonPat, productionSet: prodsAndActs.prods, augmentedStartSymbol: prodsAndActs.augStartSym, errorSymbol: symTabAndLexSpec.errSym, @@ -383,18 +381,14 @@ func collectUserDefinedIDsFromDirective(dir *spec.DirectiveNode) []string { } type symbolTableAndLexSpec struct { - symTab *symbolTable - anonPat2Sym map[string]symbol - sym2AnonPat map[symbol]string - lexSpec *mlspec.LexSpec - errSym symbol - skip []mlspec.LexKindName - skipSyms []string + symTab *symbolTable + lexSpec *mlspec.LexSpec + errSym symbol + skip []mlspec.LexKindName + skipSyms []string } func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolTableAndLexSpec, error) { - // Anonymous patterns take precedence over explicitly defined lexical specifications (named patterns). - // Thus anonymous patterns must be registered to `symTab` and `entries` before named patterns. symTab := newSymbolTable() entries := []*mlspec.LexEntry{} @@ -408,57 +402,6 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT errSym = sym } - anonPat2Sym := map[string]symbol{} - sym2AnonPat := map[symbol]string{} - { - knownPats := map[string]struct{}{} - anonPats := []string{} - literalPats := map[string]struct{}{} - for _, prod := range root.Productions { - for _, alt := range prod.RHS { - for _, elem := range alt.Elements { - if elem.Pattern == "" { - continue - } - - var pattern string - if elem.Literally { - pattern = mlspec.EscapePattern(elem.Pattern) - } else { - pattern = elem.Pattern - } - - if _, ok := knownPats[pattern]; ok { - continue - } - - knownPats[pattern] = struct{}{} - anonPats = append(anonPats, pattern) - if elem.Literally { - literalPats[pattern] = struct{}{} - } - } - } - } - - for i, p := range anonPats { - kind := fmt.Sprintf("x_%v", i+1) - - sym, err := symTab.registerTerminalSymbol(kind) - if err != nil { - return nil, err - } - - anonPat2Sym[p] = sym - sym2AnonPat[sym] = p - - entries = append(entries, &mlspec.LexEntry{ - Kind: mlspec.LexKindName(kind), - Pattern: mlspec.LexPattern(p), - }) - } - } - skipKinds := []mlspec.LexKindName{} skipSyms := []string{} for _, prod := range root.LexProductions { @@ -522,9 +465,7 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT } return &symbolTableAndLexSpec{ - symTab: symTab, - anonPat2Sym: anonPat2Sym, - sym2AnonPat: sym2AnonPat, + symTab: symTab, lexSpec: &mlspec.LexSpec{ Entries: entries, }, @@ -652,7 +593,6 @@ type productionsAndActions struct { func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAndLexSpec *symbolTableAndLexSpec) (*productionsAndActions, error) { symTab := symTabAndLexSpec.symTab - anonPat2Sym := symTabAndLexSpec.anonPat2Sym errSym := symTabAndLexSpec.errSym if len(root.Productions) == 0 { @@ -751,33 +691,15 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd offsets := map[string]int{} ambiguousIDOffsets := map[string]struct{}{} for i, elem := range alt.Elements { - var sym symbol - if elem.Pattern != "" { - var pattern string - if elem.Literally { - pattern = mlspec.EscapePattern(elem.Pattern) - } else { - pattern = elem.Pattern - } - - var ok bool - sym, ok = anonPat2Sym[pattern] - if !ok { - // All patterns are assumed to be pre-detected, so it's a bug if we cannot find them here. - return nil, fmt.Errorf("pattern '%v' is undefined", pattern) - } - } else { - var ok bool - sym, ok = symTab.toSymbol(elem.ID) - if !ok { - b.errs = append(b.errs, &verr.SpecError{ - Cause: semErrUndefinedSym, - Detail: elem.ID, - Row: elem.Pos.Row, - Col: elem.Pos.Col, - }) - continue LOOP_RHS - } + sym, ok := symTab.toSymbol(elem.ID) + if !ok { + b.errs = append(b.errs, &verr.SpecError{ + Cause: semErrUndefinedSym, + Detail: elem.ID, + Row: elem.Pos.Row, + Col: elem.Pos.Col, + }) + continue LOOP_RHS } altSyms[i] = sym @@ -933,6 +855,9 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd if param.Expansion { elem := alt.Elements[offset] if elem.Pattern != "" { + // Currently, it is a bug to reach here because it is + // forbidden to have anything other than ID appear in + // production rules. b.errs = append(b.errs, &verr.SpecError{ Cause: semErrDirInvalidParam, Detail: fmt.Sprintf("the expansion symbol cannot be applied to a pattern (%v: \"%v\")", param.ID, elem.Pattern), @@ -1319,13 +1244,6 @@ func Compile(gram *Grammar, opts ...CompileOption) (*spec.CompiledGrammar, *spec if err != nil { return nil, nil, err } - terms := make([]string, len(termTexts)) - for i, t := range termTexts { - // NOTE: For anonymous symbol, `t` is a name with `x_` as a prefix. However, - // this name is not intentionally set by a user, so a message containing this - // name will result in an unfriendly message. - terms[i] = t - } nonTerms, err := gram.symbolTable.nonTerminalTexts() if err != nil { @@ -1353,10 +1271,9 @@ func Compile(gram *Grammar, opts ...CompileOption) (*spec.CompiledGrammar, *spec b := &lrTableBuilder{ automaton: lalr1.lr0Automaton, prods: gram.productionSet, - termCount: len(terms), + termCount: len(termTexts), nonTermCount: len(nonTerms), symTab: gram.symbolTable, - sym2AnonPat: gram.sym2AnonPat, precAndAssoc: gram.precAndAssoc, } tab, err = b.build() @@ -1426,7 +1343,7 @@ func Compile(gram *Grammar, opts ...CompileOption) (*spec.CompiledGrammar, *spec StartProduction: productionNumStart.Int(), LHSSymbols: lhsSyms, AlternativeSymbolCounts: altSymCounts, - Terminals: terms, + Terminals: termTexts, TerminalCount: tab.terminalCount, NonTerminals: nonTerms, NonTerminalCount: tab.nonTerminalCount, diff --git a/grammar/grammar_test.go b/grammar/grammar_test.go index 80613aa..f6cb681 100644 --- a/grammar/grammar_test.go +++ b/grammar/grammar_test.go @@ -1723,12 +1723,14 @@ foo ); s - : foo ';' - | error ';' + : foo semi_colon + | error semi_colon ; foo : 'foo'; +semi_colon + : ';'; `, errs: []*SemanticError{semErrDirInvalidParam}, }, @@ -1965,12 +1967,14 @@ foo ); s - : foo ';' - | error ';' + : foo semi_colon + | error semi_colon ; foo : 'foo'; +semi_colon + : ';'; `, errs: []*SemanticError{semErrDirInvalidParam}, }, @@ -2207,12 +2211,14 @@ foo ); s - : foo ';' - | error ';' + : foo semi_colon + | error semi_colon ; foo : 'foo'; +semi_colon + : ';'; `, errs: []*SemanticError{semErrDirInvalidParam}, }, @@ -2675,34 +2681,6 @@ s : foo #ast foo... ; -foo - : "foo"; -`, - errs: []*SemanticError{semErrDirInvalidParam}, - }, - { - caption: "the expansion operator cannot be applied to a pattern", - specSrc: ` -#name test; - -s - : foo 'bar'@b #ast foo b... - ; - -foo - : "foo"; -`, - errs: []*SemanticError{semErrDirInvalidParam}, - }, - { - caption: "the expansion operator cannot be applied to a string", - specSrc: ` -#name test; - -s - : foo 'bar'@b #ast foo b... - ; - foo : "foo"; `, diff --git a/grammar/parsing_table.go b/grammar/parsing_table.go index e980902..1eaf63d 100644 --- a/grammar/parsing_table.go +++ b/grammar/parsing_table.go @@ -152,7 +152,6 @@ type lrTableBuilder struct { termCount int nonTermCount int symTab *symbolTable - sym2AnonPat map[symbol]string precAndAssoc *precAndAssoc conflicts []conflict @@ -328,12 +327,6 @@ func (b *lrTableBuilder) genReport(tab *ParsingTable, gram *Grammar) (*spec.Repo Name: name, } - pat, ok := b.sym2AnonPat[sym] - if ok { - term.Anonymous = true - term.Pattern = pat - } - prec := b.precAndAssoc.terminalPrecedence(sym.num()) if prec != precNil { term.Precedence = prec diff --git a/spec/grammar/description.go b/spec/grammar/description.go index 68b16be..0d2a0b7 100644 --- a/spec/grammar/description.go +++ b/spec/grammar/description.go @@ -3,7 +3,6 @@ package grammar type Terminal struct { Number int `json:"number"` Name string `json:"name"` - Anonymous bool `json:"anonymous"` Pattern string `json:"pattern"` Precedence int `json:"prec"` Associativity string `json:"assoc"` diff --git a/spec/grammar/parser.go b/spec/grammar/parser.go index 946d877..27a7c7d 100644 --- a/spec/grammar/parser.go +++ b/spec/grammar/parser.go @@ -351,7 +351,7 @@ func (p *parser) parseProduction() *ProductionNode { if !prod.isLexical() { for _, alt := range prod.RHS { for _, elem := range alt.Elements { - if elem.Pattern != "" && !elem.Literally { + if elem.Pattern != "" { raiseSyntaxError(elem.Pos.Row, synErrPatternInAlt) } } diff --git a/spec/grammar/parser_test.go b/spec/grammar/parser_test.go index 4fd7e9f..5a2e07f 100644 --- a/spec/grammar/parser_test.go +++ b/spec/grammar/parser_test.go @@ -272,56 +272,102 @@ func TestParse(t *testing.T) { { caption: "multiple productions are a valid grammar", src: ` -e: e '+' t | e '-' t | t; -t: t '*' f | t '/' f | f; -f: '(' e ')' | id; -id: "[A-Za-z_][0-9A-Za-z_]*"; +e + : e add t + | e sub t + | t + ; +t + : t mul f + | t div f + | f + ; +f + : l_paren e r_paren + | id + ; + +add + : '+'; +sub + : '-'; +mul + : '*'; +div + : '/'; +l_paren + : '('; +r_paren + : ')'; +id + : "[A-Za-z_][0-9A-Za-z_]*"; `, ast: &RootNode{ Productions: []*ProductionNode{ prod("e", - alt(id("e"), pat(`+`), id("t")), - alt(id("e"), pat(`-`), id("t")), + alt(id("e"), id("add"), id("t")), + alt(id("e"), id("sub"), id("t")), alt(id("t")), ), prod("t", - alt(id("t"), pat(`*`), id("f")), - alt(id("t"), pat(`/`), id("f")), + alt(id("t"), id("mul"), id("f")), + alt(id("t"), id("div"), id("f")), alt(id("f")), ), prod("f", - alt(pat(`(`), id("e"), pat(`)`)), + alt(id("l_paren"), id("e"), id("r_paren")), alt(id("id")), ), }, LexProductions: []*ProductionNode{ - prod("id", - alt(pat(`[A-Za-z_][0-9A-Za-z_]*`)), - ), + prod("add", alt(pat(`+`))), + prod("sub", alt(pat(`-`))), + prod("mul", alt(pat(`*`))), + prod("div", alt(pat(`/`))), + prod("l_paren", alt(pat(`(`))), + prod("r_paren", alt(pat(`)`))), + prod("id", alt(pat(`[A-Za-z_][0-9A-Za-z_]*`))), }, }, }, { caption: "productions can contain the empty alternative", src: ` -a: 'foo' | ; -b: | 'bar'; -c: ; +a + : foo + | + ; +b + : + | bar + ; +c + : + ; + +foo + : 'foo'; +bar + : 'bar'; `, ast: &RootNode{ Productions: []*ProductionNode{ prod("a", - alt(pat(`foo`)), + alt(id("foo")), alt(), ), prod("b", alt(), - alt(pat(`bar`)), + alt(id("bar")), ), prod("c", alt(), ), }, + LexProductions: []*ProductionNode{ + prod("foo", alt(pat(`foo`))), + prod("bar", alt(pat(`bar`))), + }, }, }, { @@ -332,35 +378,23 @@ a: $x; synErr: synErrNoSemicolon, }, { - caption: "an alternative can contain a string literal without a terminal symbol", + caption: "an alternative cannot contain a pattern directly", src: ` s - : 'foo' bar + : "foo" bar ; bar - : 'bar'; + : "bar"; `, - ast: &RootNode{ - Productions: []*ProductionNode{ - prod("s", - alt(pat(`foo`), id("bar")), - ), - }, - LexProductions: []*ProductionNode{ - prod("bar", - alt(pat(`bar`)), - ), - }, - }, + synErr: synErrPatternInAlt, }, { - caption: "an alternative cannot contain a pattern directly", + caption: "an alternative cannot contain a string directly", src: ` s - : "foo" bar + : 'foo' bar ; - bar : "bar"; `, @@ -721,12 +755,14 @@ a caption: "an AST has node positions", src: ` exp - : exp '+' id #ast exp id + : exp add id #ast exp id | id ; whitespace #skip : "\u{0020}+"; +add + : '+'; id : "\f{letter}(\f{letter}|\f{number})*"; fragment letter @@ -743,7 +779,7 @@ fragment number withAltDir( alt( withElemPos(id("exp"), newPos(3)), - withElemPos(pat(`+`), newPos(3)), + withElemPos(id("add"), newPos(3)), withElemPos(id("id"), newPos(3)), ), withDirPos( @@ -788,11 +824,11 @@ fragment number newPos(7), ), withProdPos( - prod("id", + prod("add", withAltPos( alt( withElemPos( - pat(`\f{letter}(\f{letter}|\f{number})*`), + pat(`+`), newPos(10), ), ), @@ -801,15 +837,29 @@ fragment number ), newPos(9), ), + withProdPos( + prod("id", + withAltPos( + alt( + withElemPos( + pat(`\f{letter}(\f{letter}|\f{number})*`), + newPos(12), + ), + ), + newPos(12), + ), + ), + newPos(11), + ), }, Fragments: []*FragmentNode{ withFragmentPos( frag("letter", "[A-Za-z_]"), - newPos(11), + newPos(13), ), withFragmentPos( frag("number", "[0-9]"), - newPos(13), + newPos(15), ), }, }, diff --git a/spec/test/parser.go b/spec/test/parser.go index c30d45c..b7265d7 100644 --- a/spec/test/parser.go +++ b/spec/test/parser.go @@ -78,11 +78,7 @@ func (t *Tree) format(buf *bytes.Buffer, depth int) { buf.WriteString(" ") } buf.WriteString("(") - if t.Kind == "" { - buf.WriteString("") - } else { - buf.WriteString(t.Kind) - } + buf.WriteString(t.Kind) if len(t.Children) > 0 { buf.WriteString("\n") for i, c := range t.Children { diff --git a/spec/test/tree-report.json b/spec/test/tree-report.json index 3bfba2c..c2018e5 100644 --- a/spec/test/tree-report.json +++ b/spec/test/tree-report.json @@ -1 +1 @@ -{"terminals":[null,{"number":1,"name":"\u003ceof\u003e","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":2,"name":"error","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":3,"name":"ws","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":4,"name":"l_paren","anonymous":false,"pattern":"","prec":1,"assoc":""},{"number":5,"name":"r_paren","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":6,"name":"identifier","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":7,"name":"raw_string_open","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":8,"name":"raw_string_body","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":9,"name":"raw_string_close","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":10,"name":"interpreted_string_open","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":11,"name":"interpreted_seq","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":12,"name":"codepoint_prefix","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":13,"name":"l_brace","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":14,"name":"r_brace","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":15,"name":"hex_digits","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":16,"name":"escaped_seq","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":17,"name":"escape_char","anonymous":false,"pattern":"","prec":0,"assoc":""},{"number":18,"name":"interpreted_string_close","anonymous":false,"pattern":"","prec":0,"assoc":""}],"non_terminals":[null,{"number":1,"name":"tree'"},{"number":2,"name":"tree"},{"number":3,"name":"tree_list"},{"number":4,"name":"string"},{"number":5,"name":"raw_string"},{"number":6,"name":"opt_raw_string_body"},{"number":7,"name":"interpreted_string"},{"number":8,"name":"opt_interpreted_string_body"},{"number":9,"name":"interpreted_string_body"},{"number":10,"name":"interpreted_string_elem"},{"number":11,"name":"codepoint_expr"}],"productions":[null,{"number":1,"lhs":1,"rhs":[-2],"prec":0,"assoc":""},{"number":2,"lhs":2,"rhs":[4,6,-3,5],"prec":0,"assoc":""},{"number":3,"lhs":2,"rhs":[4,6,-4,5],"prec":0,"assoc":""},{"number":4,"lhs":2,"rhs":[4,2,5],"prec":0,"assoc":""},{"number":5,"lhs":3,"rhs":[-3,-2],"prec":0,"assoc":""},{"number":6,"lhs":3,"rhs":[-2],"prec":0,"assoc":""},{"number":7,"lhs":3,"rhs":[],"prec":2,"assoc":""},{"number":8,"lhs":4,"rhs":[-5],"prec":0,"assoc":""},{"number":9,"lhs":4,"rhs":[-7],"prec":0,"assoc":""},{"number":10,"lhs":5,"rhs":[7,-6,9],"prec":0,"assoc":""},{"number":11,"lhs":6,"rhs":[8],"prec":0,"assoc":""},{"number":12,"lhs":6,"rhs":[],"prec":0,"assoc":""},{"number":13,"lhs":7,"rhs":[10,-8,18],"prec":0,"assoc":""},{"number":14,"lhs":7,"rhs":[10,2,18],"prec":0,"assoc":""},{"number":15,"lhs":8,"rhs":[-9],"prec":0,"assoc":""},{"number":16,"lhs":8,"rhs":[],"prec":0,"assoc":""},{"number":17,"lhs":9,"rhs":[-9,-10],"prec":0,"assoc":""},{"number":18,"lhs":9,"rhs":[-10],"prec":0,"assoc":""},{"number":19,"lhs":10,"rhs":[11],"prec":0,"assoc":""},{"number":20,"lhs":10,"rhs":[13],"prec":0,"assoc":""},{"number":21,"lhs":10,"rhs":[14],"prec":0,"assoc":""},{"number":22,"lhs":10,"rhs":[15],"prec":0,"assoc":""},{"number":23,"lhs":10,"rhs":[16],"prec":0,"assoc":""},{"number":24,"lhs":10,"rhs":[17],"prec":0,"assoc":""},{"number":25,"lhs":10,"rhs":[-11],"prec":0,"assoc":""},{"number":26,"lhs":11,"rhs":[12,13,15,14],"prec":0,"assoc":""}],"states":[{"number":0,"kernel":[{"production":1,"dot":0}],"shift":[{"symbol":4,"state":2}],"reduce":null,"goto":[{"symbol":2,"state":1}],"sr_conflict":[],"rr_conflict":[]},{"number":1,"kernel":[{"production":1,"dot":1}],"shift":null,"reduce":[{"look_ahead":[1],"production":1}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":2,"kernel":[{"production":2,"dot":1},{"production":3,"dot":1},{"production":4,"dot":1}],"shift":[{"symbol":2,"state":3},{"symbol":6,"state":4}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":3,"kernel":[{"production":4,"dot":2}],"shift":[{"symbol":5,"state":5}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":4,"kernel":[{"production":2,"dot":2},{"production":3,"dot":2}],"shift":[{"symbol":4,"state":2},{"symbol":7,"state":11},{"symbol":10,"state":12}],"reduce":[{"look_ahead":[5,1],"production":7}],"goto":[{"symbol":2,"state":6},{"symbol":3,"state":7},{"symbol":4,"state":8},{"symbol":5,"state":9},{"symbol":7,"state":10}],"sr_conflict":[{"symbol":4,"state":2,"production":7,"adopted_state":2,"adopted_production":null,"resolved_by":1}],"rr_conflict":[]},{"number":5,"kernel":[{"production":4,"dot":3}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":4}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":6,"kernel":[{"production":6,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5],"production":6}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":7,"kernel":[{"production":2,"dot":3},{"production":5,"dot":1}],"shift":[{"symbol":4,"state":2},{"symbol":5,"state":14}],"reduce":null,"goto":[{"symbol":2,"state":13}],"sr_conflict":[],"rr_conflict":[]},{"number":8,"kernel":[{"production":3,"dot":3}],"shift":[{"symbol":5,"state":15}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":9,"kernel":[{"production":8,"dot":1}],"shift":null,"reduce":[{"look_ahead":[5],"production":8}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":10,"kernel":[{"production":9,"dot":1}],"shift":null,"reduce":[{"look_ahead":[5],"production":9}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":11,"kernel":[{"production":10,"dot":1}],"shift":[{"symbol":8,"state":17}],"reduce":[{"look_ahead":[4,5,9,1],"production":12}],"goto":[{"symbol":6,"state":16}],"sr_conflict":[],"rr_conflict":[]},{"number":12,"kernel":[{"production":13,"dot":1},{"production":14,"dot":1}],"shift":[{"symbol":2,"state":22},{"symbol":11,"state":23},{"symbol":12,"state":24},{"symbol":13,"state":25},{"symbol":14,"state":26},{"symbol":15,"state":27},{"symbol":16,"state":28},{"symbol":17,"state":29}],"reduce":[{"look_ahead":[4,5,18,1],"production":16}],"goto":[{"symbol":8,"state":18},{"symbol":9,"state":19},{"symbol":10,"state":20},{"symbol":11,"state":21}],"sr_conflict":[],"rr_conflict":[]},{"number":13,"kernel":[{"production":5,"dot":2}],"shift":null,"reduce":[{"look_ahead":[4,5],"production":5}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":14,"kernel":[{"production":2,"dot":4}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":2}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":15,"kernel":[{"production":3,"dot":4}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":3}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":16,"kernel":[{"production":10,"dot":2}],"shift":[{"symbol":9,"state":30}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":17,"kernel":[{"production":11,"dot":1}],"shift":null,"reduce":[{"look_ahead":[9],"production":11}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":18,"kernel":[{"production":13,"dot":2}],"shift":[{"symbol":18,"state":31}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":19,"kernel":[{"production":15,"dot":1},{"production":17,"dot":1}],"shift":[{"symbol":11,"state":23},{"symbol":12,"state":24},{"symbol":13,"state":25},{"symbol":14,"state":26},{"symbol":15,"state":27},{"symbol":16,"state":28},{"symbol":17,"state":29}],"reduce":[{"look_ahead":[18],"production":15}],"goto":[{"symbol":11,"state":21},{"symbol":10,"state":32}],"sr_conflict":[],"rr_conflict":[]},{"number":20,"kernel":[{"production":18,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":18}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":21,"kernel":[{"production":25,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":25}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":22,"kernel":[{"production":14,"dot":2}],"shift":[{"symbol":18,"state":33}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":23,"kernel":[{"production":19,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":19}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":24,"kernel":[{"production":26,"dot":1}],"shift":[{"symbol":13,"state":34}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":25,"kernel":[{"production":20,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":20}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":26,"kernel":[{"production":21,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":21}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":27,"kernel":[{"production":22,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":22}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":28,"kernel":[{"production":23,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":23}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":29,"kernel":[{"production":24,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":24}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":30,"kernel":[{"production":10,"dot":3}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":10}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":31,"kernel":[{"production":13,"dot":3}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":13}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":32,"kernel":[{"production":17,"dot":2}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":17}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":33,"kernel":[{"production":14,"dot":3}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":14}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":34,"kernel":[{"production":26,"dot":2}],"shift":[{"symbol":15,"state":35}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":35,"kernel":[{"production":26,"dot":3}],"shift":[{"symbol":14,"state":36}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":36,"kernel":[{"production":26,"dot":4}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":26}],"goto":null,"sr_conflict":[],"rr_conflict":[]}]} +{"terminals":[null,{"number":1,"name":"\u003ceof\u003e","pattern":"","prec":0,"assoc":""},{"number":2,"name":"error","pattern":"","prec":0,"assoc":""},{"number":3,"name":"ws","pattern":"","prec":0,"assoc":""},{"number":4,"name":"l_paren","pattern":"","prec":1,"assoc":""},{"number":5,"name":"r_paren","pattern":"","prec":0,"assoc":""},{"number":6,"name":"identifier","pattern":"","prec":0,"assoc":""},{"number":7,"name":"raw_string_open","pattern":"","prec":0,"assoc":""},{"number":8,"name":"raw_string_body","pattern":"","prec":0,"assoc":""},{"number":9,"name":"raw_string_close","pattern":"","prec":0,"assoc":""},{"number":10,"name":"interpreted_string_open","pattern":"","prec":0,"assoc":""},{"number":11,"name":"interpreted_seq","pattern":"","prec":0,"assoc":""},{"number":12,"name":"codepoint_prefix","pattern":"","prec":0,"assoc":""},{"number":13,"name":"l_brace","pattern":"","prec":0,"assoc":""},{"number":14,"name":"r_brace","pattern":"","prec":0,"assoc":""},{"number":15,"name":"hex_digits","pattern":"","prec":0,"assoc":""},{"number":16,"name":"escaped_seq","pattern":"","prec":0,"assoc":""},{"number":17,"name":"escape_char","pattern":"","prec":0,"assoc":""},{"number":18,"name":"interpreted_string_close","pattern":"","prec":0,"assoc":""}],"non_terminals":[null,{"number":1,"name":"tree'"},{"number":2,"name":"tree"},{"number":3,"name":"tree_list"},{"number":4,"name":"string"},{"number":5,"name":"raw_string"},{"number":6,"name":"opt_raw_string_body"},{"number":7,"name":"interpreted_string"},{"number":8,"name":"opt_interpreted_string_body"},{"number":9,"name":"interpreted_string_body"},{"number":10,"name":"interpreted_string_elem"},{"number":11,"name":"codepoint_expr"}],"productions":[null,{"number":1,"lhs":1,"rhs":[-2],"prec":0,"assoc":""},{"number":2,"lhs":2,"rhs":[4,6,-3,5],"prec":0,"assoc":""},{"number":3,"lhs":2,"rhs":[4,6,-4,5],"prec":0,"assoc":""},{"number":4,"lhs":2,"rhs":[4,2,5],"prec":0,"assoc":""},{"number":5,"lhs":3,"rhs":[-3,-2],"prec":0,"assoc":""},{"number":6,"lhs":3,"rhs":[-2],"prec":0,"assoc":""},{"number":7,"lhs":3,"rhs":[],"prec":2,"assoc":""},{"number":8,"lhs":4,"rhs":[-5],"prec":0,"assoc":""},{"number":9,"lhs":4,"rhs":[-7],"prec":0,"assoc":""},{"number":10,"lhs":5,"rhs":[7,-6,9],"prec":0,"assoc":""},{"number":11,"lhs":6,"rhs":[8],"prec":0,"assoc":""},{"number":12,"lhs":6,"rhs":[],"prec":0,"assoc":""},{"number":13,"lhs":7,"rhs":[10,-8,18],"prec":0,"assoc":""},{"number":14,"lhs":7,"rhs":[10,2,18],"prec":0,"assoc":""},{"number":15,"lhs":8,"rhs":[-9],"prec":0,"assoc":""},{"number":16,"lhs":8,"rhs":[],"prec":0,"assoc":""},{"number":17,"lhs":9,"rhs":[-9,-10],"prec":0,"assoc":""},{"number":18,"lhs":9,"rhs":[-10],"prec":0,"assoc":""},{"number":19,"lhs":10,"rhs":[11],"prec":0,"assoc":""},{"number":20,"lhs":10,"rhs":[13],"prec":0,"assoc":""},{"number":21,"lhs":10,"rhs":[14],"prec":0,"assoc":""},{"number":22,"lhs":10,"rhs":[15],"prec":0,"assoc":""},{"number":23,"lhs":10,"rhs":[16],"prec":0,"assoc":""},{"number":24,"lhs":10,"rhs":[17],"prec":0,"assoc":""},{"number":25,"lhs":10,"rhs":[-11],"prec":0,"assoc":""},{"number":26,"lhs":11,"rhs":[12,13,15,14],"prec":0,"assoc":""}],"states":[{"number":0,"kernel":[{"production":1,"dot":0}],"shift":[{"symbol":4,"state":2}],"reduce":null,"goto":[{"symbol":2,"state":1}],"sr_conflict":[],"rr_conflict":[]},{"number":1,"kernel":[{"production":1,"dot":1}],"shift":null,"reduce":[{"look_ahead":[1],"production":1}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":2,"kernel":[{"production":2,"dot":1},{"production":3,"dot":1},{"production":4,"dot":1}],"shift":[{"symbol":2,"state":3},{"symbol":6,"state":4}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":3,"kernel":[{"production":4,"dot":2}],"shift":[{"symbol":5,"state":5}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":4,"kernel":[{"production":2,"dot":2},{"production":3,"dot":2}],"shift":[{"symbol":4,"state":2},{"symbol":7,"state":11},{"symbol":10,"state":12}],"reduce":[{"look_ahead":[5,1],"production":7}],"goto":[{"symbol":2,"state":6},{"symbol":3,"state":7},{"symbol":4,"state":8},{"symbol":5,"state":9},{"symbol":7,"state":10}],"sr_conflict":[{"symbol":4,"state":2,"production":7,"adopted_state":2,"adopted_production":null,"resolved_by":1}],"rr_conflict":[]},{"number":5,"kernel":[{"production":4,"dot":3}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":4}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":6,"kernel":[{"production":6,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5],"production":6}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":7,"kernel":[{"production":2,"dot":3},{"production":5,"dot":1}],"shift":[{"symbol":4,"state":2},{"symbol":5,"state":14}],"reduce":null,"goto":[{"symbol":2,"state":13}],"sr_conflict":[],"rr_conflict":[]},{"number":8,"kernel":[{"production":3,"dot":3}],"shift":[{"symbol":5,"state":15}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":9,"kernel":[{"production":8,"dot":1}],"shift":null,"reduce":[{"look_ahead":[5],"production":8}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":10,"kernel":[{"production":9,"dot":1}],"shift":null,"reduce":[{"look_ahead":[5],"production":9}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":11,"kernel":[{"production":10,"dot":1}],"shift":[{"symbol":8,"state":17}],"reduce":[{"look_ahead":[4,5,9,1],"production":12}],"goto":[{"symbol":6,"state":16}],"sr_conflict":[],"rr_conflict":[]},{"number":12,"kernel":[{"production":13,"dot":1},{"production":14,"dot":1}],"shift":[{"symbol":2,"state":22},{"symbol":11,"state":23},{"symbol":12,"state":24},{"symbol":13,"state":25},{"symbol":14,"state":26},{"symbol":15,"state":27},{"symbol":16,"state":28},{"symbol":17,"state":29}],"reduce":[{"look_ahead":[4,5,18,1],"production":16}],"goto":[{"symbol":8,"state":18},{"symbol":9,"state":19},{"symbol":10,"state":20},{"symbol":11,"state":21}],"sr_conflict":[],"rr_conflict":[]},{"number":13,"kernel":[{"production":5,"dot":2}],"shift":null,"reduce":[{"look_ahead":[4,5],"production":5}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":14,"kernel":[{"production":2,"dot":4}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":2}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":15,"kernel":[{"production":3,"dot":4}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":3}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":16,"kernel":[{"production":10,"dot":2}],"shift":[{"symbol":9,"state":30}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":17,"kernel":[{"production":11,"dot":1}],"shift":null,"reduce":[{"look_ahead":[9],"production":11}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":18,"kernel":[{"production":13,"dot":2}],"shift":[{"symbol":18,"state":31}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":19,"kernel":[{"production":15,"dot":1},{"production":17,"dot":1}],"shift":[{"symbol":11,"state":23},{"symbol":12,"state":24},{"symbol":13,"state":25},{"symbol":14,"state":26},{"symbol":15,"state":27},{"symbol":16,"state":28},{"symbol":17,"state":29}],"reduce":[{"look_ahead":[18],"production":15}],"goto":[{"symbol":11,"state":21},{"symbol":10,"state":32}],"sr_conflict":[],"rr_conflict":[]},{"number":20,"kernel":[{"production":18,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":18}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":21,"kernel":[{"production":25,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":25}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":22,"kernel":[{"production":14,"dot":2}],"shift":[{"symbol":18,"state":33}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":23,"kernel":[{"production":19,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":19}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":24,"kernel":[{"production":26,"dot":1}],"shift":[{"symbol":13,"state":34}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":25,"kernel":[{"production":20,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":20}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":26,"kernel":[{"production":21,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":21}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":27,"kernel":[{"production":22,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":22}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":28,"kernel":[{"production":23,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":23}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":29,"kernel":[{"production":24,"dot":1}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":24}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":30,"kernel":[{"production":10,"dot":3}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":10}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":31,"kernel":[{"production":13,"dot":3}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":13}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":32,"kernel":[{"production":17,"dot":2}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":17}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":33,"kernel":[{"production":14,"dot":3}],"shift":null,"reduce":[{"look_ahead":[4,5,1],"production":14}],"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":34,"kernel":[{"production":26,"dot":2}],"shift":[{"symbol":15,"state":35}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":35,"kernel":[{"production":26,"dot":3}],"shift":[{"symbol":14,"state":36}],"reduce":null,"goto":null,"sr_conflict":[],"rr_conflict":[]},{"number":36,"kernel":[{"production":26,"dot":4}],"shift":null,"reduce":[{"look_ahead":[4,5,11,12,13,14,15,16,17,18,1],"production":26}],"goto":null,"sr_conflict":[],"rr_conflict":[]}]} diff --git a/spec/test/tree_semantic_action.go b/spec/test/tree_semantic_action.go index c426183..c1d5a25 100644 --- a/spec/test/tree_semantic_action.go +++ b/spec/test/tree_semantic_action.go @@ -341,11 +341,7 @@ func printTree(w io.Writer, node *Node, ruledLine string, childRuledLinePrefix s case NodeTypeError: fmt.Fprintf(w, "%v%v\n", ruledLine, node.KindName) case NodeTypeTerminal: - if node.KindName == "" { - fmt.Fprintf(w, "%v %v\n", ruledLine, strconv.Quote(node.Text)) - } else { - fmt.Fprintf(w, "%v%v %v\n", ruledLine, node.KindName, strconv.Quote(node.Text)) - } + fmt.Fprintf(w, "%v%v %v\n", ruledLine, node.KindName, strconv.Quote(node.Text)) case NodeTypeNonTerminal: fmt.Fprintf(w, "%v%v\n", ruledLine, node.KindName) -- cgit v1.2.3