aboutsummaryrefslogtreecommitdiff
path: root/grammar/grammar.go
diff options
context:
space:
mode:
Diffstat (limited to 'grammar/grammar.go')
-rw-r--r--grammar/grammar.go61
1 files changed, 35 insertions, 26 deletions
diff --git a/grammar/grammar.go b/grammar/grammar.go
index c996e36..d46d70e 100644
--- a/grammar/grammar.go
+++ b/grammar/grammar.go
@@ -39,7 +39,7 @@ type precAndAssoc struct {
termAssoc map[symbolNum]assocType
// prodPrec and prodAssoc represent the precedence and the associativities of the production.
- // These values are inherited from the right-most symbols in the RHS of the productions.
+ // These values are inherited from the right-most terminal symbols in the RHS of the productions.
prodPrec map[productionNum]int
prodAssoc map[productionNum]assocType
}
@@ -150,7 +150,7 @@ func (b *GrammarBuilder) Build() (*Grammar, error) {
return nil, b.errs
}
- pa, err := b.genPrecAndAssoc(symTabAndLexSpec.symTab, prodsAndActs.prods, prodsAndActs.prodPrecs)
+ pa, err := b.genPrecAndAssoc(symTabAndLexSpec.symTab, prodsAndActs.prods, prodsAndActs.prodPrecs, prodsAndActs.prodPrecPoss)
if err != nil {
return nil, err
}
@@ -601,6 +601,7 @@ type productionsAndActions struct {
augStartSym symbol
astActs map[productionID][]*astActionEntry
prodPrecs map[productionID]symbol
+ prodPrecPoss map[productionID]*spec.Position
recoverProds map[productionID]struct{}
}
@@ -620,6 +621,7 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
var augStartSym symbol
astActs := map[productionID][]*astActionEntry{}
prodPrecs := map[productionID]symbol{}
+ prodPrecPoss := map[productionID]*spec.Position{}
recoverProds := map[productionID]struct{}{}
startProd := root.Productions[0]
@@ -945,6 +947,7 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
continue LOOP_RHS
}
prodPrecs[p.id] = sym
+ prodPrecPoss[p.id] = &dir.Parameters[0].Pos
case "recover":
if len(dir.Parameters) > 0 {
b.errs = append(b.errs, &verr.SpecError{
@@ -974,11 +977,12 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
augStartSym: augStartSym,
astActs: astActs,
prodPrecs: prodPrecs,
+ prodPrecPoss: prodPrecPoss,
recoverProds: recoverProds,
}, nil
}
-func (b *GrammarBuilder) genPrecAndAssoc(symTab *symbolTable, prods *productionSet, prodPrecs map[productionID]symbol) (*precAndAssoc, error) {
+func (b *GrammarBuilder) genPrecAndAssoc(symTab *symbolTable, prods *productionSet, prodPrecs map[productionID]symbol, prodPrecPoss map[productionID]*spec.Position) (*precAndAssoc, error) {
termPrec := map[symbolNum]int{}
termAssoc := map[symbolNum]assocType{}
{
@@ -1082,34 +1086,39 @@ func (b *GrammarBuilder) genPrecAndAssoc(symTab *symbolTable, prods *productionS
prodPrec := map[productionNum]int{}
prodAssoc := map[productionNum]assocType{}
for _, prod := range prods.getAllProductions() {
- term, ok := prodPrecs[prod.id]
- if !ok {
- mostrightTerm := symbolNil
- for _, sym := range prod.rhs {
- if !sym.isTerminal() {
- continue
- }
- mostrightTerm = sym
+ mostrightTerm := symbolNil
+ for _, sym := range prod.rhs {
+ if !sym.isTerminal() {
+ continue
}
-
- term = mostrightTerm
+ mostrightTerm = sym
}
- if term.isNil() {
- continue
- }
-
- prec, ok := termPrec[term.num()]
- if !ok {
- continue
+ if !mostrightTerm.isNil() {
+ if prec, ok := termPrec[mostrightTerm.num()]; ok {
+ prodPrec[prod.num] = prec
+ }
+ if assoc, ok := termAssoc[mostrightTerm.num()]; ok {
+ prodAssoc[prod.num] = assoc
+ }
}
- assoc, ok := termAssoc[term.num()]
- if !ok {
- continue
+ // #prec directive changes only precedence, not associativity.
+ if term, ok := prodPrecs[prod.id]; ok {
+ if prec, ok := termPrec[term.num()]; ok {
+ prodPrec[prod.num] = prec
+ } else {
+ text, _ := symTab.toText(term)
+ b.errs = append(b.errs, &verr.SpecError{
+ Cause: semErrUndefinedPrec,
+ Detail: text,
+ Row: prodPrecPoss[prod.id].Row,
+ Col: prodPrecPoss[prod.id].Col,
+ })
+ }
}
-
- prodPrec[prod.num] = prec
- prodAssoc[prod.num] = assoc
+ }
+ if len(b.errs) > 0 {
+ return nil, nil
}
return &precAndAssoc{