diff options
author | Ryo Nihei <nihei.dev@gmail.com> | 2021-07-19 00:58:25 +0900 |
---|---|---|
committer | Ryo Nihei <nihei.dev@gmail.com> | 2021-07-19 00:58:25 +0900 |
commit | 68a644a559db0d2e117066a413e9279988576164 (patch) | |
tree | 18c384b01076832d77708bb42fb0d21dbb816c39 | |
parent | Sort error messages before printing them (diff) | |
download | cotia-68a644a559db0d2e117066a413e9279988576164.tar.gz cotia-68a644a559db0d2e117066a413e9279988576164.tar.xz |
Detect duplicate definitions of terminal symbols and fragments in advance
-rw-r--r-- | grammar/grammar.go | 20 | ||||
-rw-r--r-- | grammar/semantic_error.go | 1 |
2 files changed, 21 insertions, 0 deletions
diff --git a/grammar/grammar.go b/grammar/grammar.go index 0cd055d..00c894c 100644 --- a/grammar/grammar.go +++ b/grammar/grammar.go @@ -66,6 +66,15 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT skipKinds := []mlspec.LexKind{} entries := []*mlspec.LexEntry{} for _, prod := range root.LexProductions { + if _, exist := symTab.toSymbol(prod.LHS); exist { + b.errs = append(b.errs, &verr.SpecError{ + Cause: semErrDuplicateSym, + Detail: prod.LHS, + Row: prod.Pos.Row, + }) + continue + } + _, err := symTab.registerTerminalSymbol(prod.LHS) if err != nil { return nil, err @@ -129,7 +138,18 @@ func (b *GrammarBuilder) genSymbolTableAndLexSpec(root *spec.RootNode) (*symbolT // Anonymous patterns take precedence over explicitly defined lexical specifications. entries = append(anonEntries, entries...) + checkedFragments := map[string]struct{}{} for _, fragment := range root.Fragments { + if _, exist := checkedFragments[fragment.LHS]; exist { + b.errs = append(b.errs, &verr.SpecError{ + Cause: semErrDuplicateSym, + Detail: fragment.LHS, + Row: fragment.Pos.Row, + }) + continue + } + checkedFragments[fragment.LHS] = struct{}{} + entries = append(entries, &mlspec.LexEntry{ Fragment: true, Kind: mlspec.LexKind(fragment.LHS), diff --git a/grammar/semantic_error.go b/grammar/semantic_error.go index 01446ed..63f9325 100644 --- a/grammar/semantic_error.go +++ b/grammar/semantic_error.go @@ -17,6 +17,7 @@ func (e *SemanticError) Error() string { var ( semErrNoProduction = newSemanticError("a grammar needs at least one production") semErrUndefinedSym = newSemanticError("undefined symbol") + semErrDuplicateSym = newSemanticError("duplicate symbol") semErrDirInvalidName = newSemanticError("invalid directive name") semErrDirInvalidParam = newSemanticError("invalid parameter") ) |