diff options
Diffstat (limited to 'grammar/grammar.go')
-rw-r--r-- | grammar/grammar.go | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/grammar/grammar.go b/grammar/grammar.go index 7cd2409..6130e55 100644 --- a/grammar/grammar.go +++ b/grammar/grammar.go @@ -3,6 +3,7 @@ package grammar import ( "fmt" "os" + "strings" mlcompiler "github.com/nihei9/maleeni/compiler" mlspec "github.com/nihei9/maleeni/spec" @@ -343,6 +344,42 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd if err != nil { return nil, err } + if _, exist := prods.findByID(p.id); exist { + // Report the line number of a duplicate alternative. + // When the alternative is empty, we report the position of its LHS. + var row int + if len(alt.Elements) > 0 { + row = alt.Elements[0].Pos.Row + } else { + row = prod.Pos.Row + } + + var detail string + { + var b strings.Builder + fmt.Fprintf(&b, "%v →", prod.LHS) + for _, elem := range alt.Elements { + switch { + case elem.ID != "": + fmt.Fprintf(&b, " %v", elem.ID) + case elem.Pattern != "": + fmt.Fprintf(&b, ` "%v"`, elem.Pattern) + } + } + if len(alt.Elements) == 0 { + fmt.Fprintf(&b, " ε") + } + + detail = b.String() + } + + b.errs = append(b.errs, &verr.SpecError{ + Cause: semErrDuplicateProduction, + Detail: detail, + Row: row, + }) + continue LOOP_RHS + } prods.append(p) if alt.Directive != nil { |