aboutsummaryrefslogtreecommitdiff
path: root/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'grammar')
-rw-r--r--grammar/grammar.go30
-rw-r--r--grammar/semantic_error.go1
2 files changed, 26 insertions, 5 deletions
diff --git a/grammar/grammar.go b/grammar/grammar.go
index c5726d7..2cdf2b3 100644
--- a/grammar/grammar.go
+++ b/grammar/grammar.go
@@ -571,12 +571,12 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
}
}
- if alt.Directive != nil {
+ if len(alt.Directives) > 0 {
return nil, false, "", &verr.SpecError{
Cause: semErrInvalidAltDir,
Detail: "a lexical production cannot have alternative directives",
- Row: alt.Directive.Pos.Row,
- Col: alt.Directive.Pos.Col,
+ Row: alt.Directives[0].Pos.Row,
+ Col: alt.Directives[0].Pos.Col,
}, nil
}
@@ -680,6 +680,16 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
return nil, fmt.Errorf("symbol '%v' is undefined", prod.LHS)
}
+ if len(prod.Directives) > 0 {
+ b.errs = append(b.errs, &verr.SpecError{
+ Cause: semErrInvalidProdDir,
+ Detail: "a production cannot have production directives",
+ Row: prod.Directives[0].Pos.Row,
+ Col: prod.Directives[0].Pos.Col,
+ })
+ continue
+ }
+
LOOP_RHS:
for _, alt := range prod.RHS {
altSyms := make([]symbol, len(alt.Elements))
@@ -788,8 +798,18 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
}
prods.append(p)
- if alt.Directive != nil {
- dir := alt.Directive
+ dirConsumed := map[string]struct{}{}
+ for _, dir := range alt.Directives {
+ if _, consumed := dirConsumed[dir.Name]; consumed {
+ b.errs = append(b.errs, &verr.SpecError{
+ Cause: semErrDuplicateDir,
+ Detail: dir.Name,
+ Row: dir.Pos.Row,
+ Col: dir.Pos.Col,
+ })
+ }
+ dirConsumed[dir.Name] = struct{}{}
+
switch dir.Name {
case "ast":
if len(dir.Parameters) == 0 {
diff --git a/grammar/semantic_error.go b/grammar/semantic_error.go
index 7ff1ba7..04cc020 100644
--- a/grammar/semantic_error.go
+++ b/grammar/semantic_error.go
@@ -32,5 +32,6 @@ var (
semErrDirInvalidName = newSemanticError("invalid directive name")
semErrDirInvalidParam = newSemanticError("invalid parameter")
semErrDuplicateDir = newSemanticError("a directive must not be duplicated")
+ semErrInvalidProdDir = newSemanticError("invalid production directive")
semErrInvalidAltDir = newSemanticError("invalid alternative directive")
)