diff options
| author | Ryo Nihei <nihei.dev@gmail.com> | 2022-03-28 22:31:30 +0900 |
|---|---|---|
| committer | Ryo Nihei <nihei.dev@gmail.com> | 2022-03-29 01:45:05 +0900 |
| commit | ed43562cf58e8c0f9390421848879308fdfc60cb (patch) | |
| tree | 16beff7d233b95ae53d2c8019bc47be378f304b8 /grammar | |
| parent | Simplify the syntax of #ast directive (diff) | |
| download | urubu-ed43562cf58e8c0f9390421848879308fdfc60cb.tar.gz urubu-ed43562cf58e8c0f9390421848879308fdfc60cb.tar.xz | |
Add label notation
Diffstat (limited to 'grammar')
| -rw-r--r-- | grammar/grammar.go | 23 | ||||
| -rw-r--r-- | grammar/semantic_error.go | 2 |
2 files changed, 25 insertions, 0 deletions
diff --git a/grammar/grammar.go b/grammar/grammar.go index 9d1933b..3f1117c 100644 --- a/grammar/grammar.go +++ b/grammar/grammar.go @@ -677,6 +677,7 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd LOOP_RHS: for _, alt := range prod.RHS { altSyms := make([]symbol, len(alt.Elements)) + labels := map[string]int{} for i, elem := range alt.Elements { var sym symbol if elem.Pattern != "" { @@ -707,6 +708,28 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd } } altSyms[i] = sym + + if elem.Label != nil { + if _, added := labels[elem.Label.Name]; added { + b.errs = append(b.errs, &verr.SpecError{ + Cause: semErrDuplicateLabel, + Detail: elem.Label.Name, + Row: elem.Label.Pos.Row, + Col: elem.Label.Pos.Col, + }) + continue LOOP_RHS + } + if _, found := symTab.toSymbol(elem.Label.Name); found { + b.errs = append(b.errs, &verr.SpecError{ + Cause: semErrInvalidLabel, + Detail: elem.Label.Name, + Row: elem.Label.Pos.Row, + Col: elem.Label.Pos.Col, + }) + continue LOOP_RHS + } + labels[elem.Label.Name] = i + } } p, err := newProduction(lhsSym, altSyms) diff --git a/grammar/semantic_error.go b/grammar/semantic_error.go index d540c03..4326d81 100644 --- a/grammar/semantic_error.go +++ b/grammar/semantic_error.go @@ -27,6 +27,8 @@ var ( semErrDuplicateTerminal = newSemanticError("duplicate terminal") semErrDuplicateName = newSemanticError("duplicate names are not allowed between terminals and non-terminals") semErrErrSymIsReserved = newSemanticError("symbol 'error' is reserved as a terminal symbol") + semErrDuplicateLabel = newSemanticError("a label must be unique in an alternative") + semErrInvalidLabel = newSemanticError("a label must differ from terminal symbols or non-terminal symbols") semErrDirInvalidName = newSemanticError("invalid directive name") semErrDirInvalidParam = newSemanticError("invalid parameter") ) |
