aboutsummaryrefslogtreecommitdiff
path: root/grammar/lr0.go
diff options
context:
space:
mode:
Diffstat (limited to 'grammar/lr0.go')
-rw-r--r--grammar/lr0.go28
1 files changed, 16 insertions, 12 deletions
diff --git a/grammar/lr0.go b/grammar/lr0.go
index 20952c8..dea5254 100644
--- a/grammar/lr0.go
+++ b/grammar/lr0.go
@@ -10,7 +10,7 @@ type lr0Automaton struct {
states map[kernelID]*lrState
}
-func genLR0Automaton(prods *productionSet, startSym symbol) (*lr0Automaton, error) {
+func genLR0Automaton(prods *productionSet, startSym symbol, errSym symbol) (*lr0Automaton, error) {
if !startSym.isStart() {
return nil, fmt.Errorf("passed symbold is not a start symbol")
}
@@ -44,7 +44,7 @@ func genLR0Automaton(prods *productionSet, startSym symbol) (*lr0Automaton, erro
for len(uncheckedKernels) > 0 {
nextUncheckedKernels := []*kernel{}
for _, k := range uncheckedKernels {
- state, neighbours, err := genStateAndNeighbourKernels(k, prods)
+ state, neighbours, err := genStateAndNeighbourKernels(k, prods, errSym)
if err != nil {
return nil, err
}
@@ -67,7 +67,7 @@ func genLR0Automaton(prods *productionSet, startSym symbol) (*lr0Automaton, erro
return automaton, nil
}
-func genStateAndNeighbourKernels(k *kernel, prods *productionSet) (*lrState, []*kernel, error) {
+func genStateAndNeighbourKernels(k *kernel, prods *productionSet, errSym symbol) (*lrState, []*kernel, error) {
items, err := genLR0Closure(k, prods)
if err != nil {
return nil, nil, err
@@ -86,19 +86,22 @@ func genStateAndNeighbourKernels(k *kernel, prods *productionSet) (*lrState, []*
reducible := map[productionID]struct{}{}
var emptyProdItems []*lrItem
+ isErrorTrapper := false
for _, item := range items {
- if !item.reducible {
- continue
+ if item.dottedSymbol == errSym {
+ isErrorTrapper = true
}
- reducible[item.prod] = struct{}{}
+ if item.reducible {
+ reducible[item.prod] = struct{}{}
- prod, ok := prods.findByID(item.prod)
- if !ok {
- return nil, nil, fmt.Errorf("reducible production not found: %v", item.prod)
- }
- if prod.isEmpty() {
- emptyProdItems = append(emptyProdItems, item)
+ prod, ok := prods.findByID(item.prod)
+ if !ok {
+ return nil, nil, fmt.Errorf("reducible production not found: %v", item.prod)
+ }
+ if prod.isEmpty() {
+ emptyProdItems = append(emptyProdItems, item)
+ }
}
}
@@ -107,6 +110,7 @@ func genStateAndNeighbourKernels(k *kernel, prods *productionSet) (*lrState, []*
next: next,
reducible: reducible,
emptyProdItems: emptyProdItems,
+ isErrorTrapper: isErrorTrapper,
}, kernels, nil
}