aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-07-20 23:38:45 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-07-20 23:40:16 +0900
commit07187ec843f1fddba0a65402925c8d3203f58a5d (patch)
tree82c63337bac7db0b113792e3c164ae6373307af8
parentDetect multiple conflicts (diff)
downloadcotia-07187ec843f1fddba0a65402925c8d3203f58a5d.tar.gz
cotia-07187ec843f1fddba0a65402925c8d3203f58a5d.tar.xz
Print pattern strings of anonymous pattern on conflict messages
-rw-r--r--grammar/grammar.go7
-rw-r--r--grammar/slr.go31
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
+}