diff options
-rw-r--r-- | grammar/grammar.go | 7 | ||||
-rw-r--r-- | grammar/slr.go | 31 |
2 files changed, 28 insertions, 10 deletions
diff --git a/grammar/grammar.go b/grammar/grammar.go index a43b133..353beef 100644 --- a/grammar/grammar.go +++ b/grammar/grammar.go @@ -17,6 +17,7 @@ type astActionEntry struct { type Grammar struct { lexSpec *mlspec.LexSpec skipLexKinds []mlspec.LexKind + sym2AnonPat map[symbol]string productionSet *productionSet augmentedStartSymbol symbol symbolTable *symbolTable @@ -47,6 +48,7 @@ func (b *GrammarBuilder) Build(root *spec.RootNode) (*Grammar, error) { return &Grammar{ lexSpec: symTabAndLexSpec.lexSpec, skipLexKinds: symTabAndLexSpec.skip, + sym2AnonPat: symTabAndLexSpec.sym2AnonPat, productionSet: prodsAndActs.prods, augmentedStartSymbol: prodsAndActs.augStartSym, symbolTable: symTabAndLexSpec.symTab, @@ -57,6 +59,7 @@ func (b *GrammarBuilder) Build(root *spec.RootNode) (*Grammar, error) { type symbolTableAndLexSpec struct { symTab *symbolTable anonPat2Sym map[string]symbol + sym2AnonPat map[symbol]string lexSpec *mlspec.LexSpec skip []mlspec.LexKind } @@ -95,6 +98,7 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT } anonPat2Sym := map[string]symbol{} + sym2AnonPat := map[symbol]string{} var anonEntries []*mlspec.LexEntry { anonPats := []string{} @@ -127,6 +131,7 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT return nil, err } anonPat2Sym[p] = sym + sym2AnonPat[sym] = p anonEntries = append(anonEntries, &mlspec.LexEntry{ Kind: mlspec.LexKind(kind), @@ -160,6 +165,7 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT return &symbolTableAndLexSpec{ symTab: symTab, anonPat2Sym: anonPat2Sym, + sym2AnonPat: sym2AnonPat, lexSpec: &mlspec.LexSpec{ Entries: entries, }, @@ -494,6 +500,7 @@ func Compile(gram *Grammar) (*spec.CompiledGrammar, error) { termCount: len(terms), nonTermCount: len(nonTerms), symTab: gram.symbolTable, + sym2AnonPat: gram.sym2AnonPat, } tab, err := slr.build() if err != nil { diff --git a/grammar/slr.go b/grammar/slr.go index 3794ab7..221bf8f 100644 --- a/grammar/slr.go +++ b/grammar/slr.go @@ -170,6 +170,7 @@ type slrTableBuilder struct { termCount int nonTermCount int symTab *symbolTable + sym2AnonPat map[symbol]string } func (b *slrTableBuilder) build() (*ParsingTable, error) { @@ -229,17 +230,9 @@ func (b *slrTableBuilder) build() (*ParsingTable, error) { fmt.Fprintf(&msg, "\n") switch c := conflict.(type) { case *shiftReduceConflict: - sym, ok := b.symTab.toText(c.sym) - if !ok { - sym = fmt.Sprintf("<not found: %v>", c.sym) - } - fmt.Fprintf(&msg, "%v: shift/reduce conflict (shift %v, reduce %v) on %v", c.state, c.nextState, c.prodNum, sym) + fmt.Fprintf(&msg, "%v: shift/reduce conflict (shift %v, reduce %v) on %v", c.state, c.nextState, c.prodNum, b.symbolToText(c.sym)) case *reduceReduceConflict: - sym, ok := b.symTab.toText(c.sym) - if !ok { - sym = fmt.Sprintf("<not found: %v>", c.sym) - } - fmt.Fprintf(&msg, "%v: reduce/reduce conflict (reduce %v and %v) on %v", c.state, c.prodNum1, c.prodNum2, sym) + fmt.Fprintf(&msg, "%v: reduce/reduce conflict (reduce %v and %v) on %v", c.state, c.prodNum1, c.prodNum2, b.symbolToText(c.sym)) } } return nil, fmt.Errorf("%v conflicts:%v", len(conflicts), msg.String()) @@ -247,3 +240,21 @@ func (b *slrTableBuilder) build() (*ParsingTable, error) { return ptab, nil } + +func (b *slrTableBuilder) symbolToText(sym symbol) string { + text, ok := b.symTab.toText(sym) + if !ok { + return fmt.Sprintf("<symbol not found: %v>", sym) + } + + if strings.HasPrefix(text, "_") { + pat, ok := b.sym2AnonPat[sym] + if !ok { + return fmt.Sprintf("<pattern not found: %v>", text) + } + + return fmt.Sprintf(`"%v"`, pat) + } + + return text +} |