aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-07-19 00:58:25 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-07-19 00:58:25 +0900
commit68a644a559db0d2e117066a413e9279988576164 (patch)
tree18c384b01076832d77708bb42fb0d21dbb816c39
parentSort error messages before printing them (diff)
downloadcotia-68a644a559db0d2e117066a413e9279988576164.tar.gz
cotia-68a644a559db0d2e117066a413e9279988576164.tar.xz
Detect duplicate definitions of terminal symbols and fragments in advance
-rw-r--r--grammar/grammar.go20
-rw-r--r--grammar/semantic_error.go1
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")
)