From adb12c2c1b2873d8775f55c02f54e6690687f1a2 Mon Sep 17 00:00:00 2001 From: Ryo Nihei Date: Wed, 28 Jul 2021 01:54:39 +0900 Subject: Detect duplicate production errors --- grammar/grammar.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'grammar/grammar.go') 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 { -- cgit v1.2.3