aboutsummaryrefslogtreecommitdiff
path: root/grammar/slr1.go
diff options
context:
space:
mode:
authorRyo Nihei <nihei.dev@gmail.com>2021-08-18 00:03:59 +0900
committerRyo Nihei <nihei.dev@gmail.com>2021-08-18 00:03:59 +0900
commite110a6ff4073799d00c7d3400ac022f758a03e40 (patch)
treee194e63debc48a53e5f9ec77075bd8ad0dcfa25f /grammar/slr1.go
parentFix panic on a syntax error (diff)
downloadcotia-e110a6ff4073799d00c7d3400ac022f758a03e40.tar.gz
cotia-e110a6ff4073799d00c7d3400ac022f758a03e40.tar.xz
Set look-ahead symbols to items before generating a SLR(1) parsing table
Diffstat (limited to 'grammar/slr1.go')
-rw-r--r--grammar/slr1.go61
1 files changed, 61 insertions, 0 deletions
diff --git a/grammar/slr1.go b/grammar/slr1.go
new file mode 100644
index 0000000..b11a66f
--- /dev/null
+++ b/grammar/slr1.go
@@ -0,0 +1,61 @@
+package grammar
+
+import "fmt"
+
+type slr1Automaton struct {
+ *lr0Automaton
+}
+
+func genSLR1Automaton(lr0 *lr0Automaton, prods *productionSet, follow *followSet) (*slr1Automaton, error) {
+ for _, state := range lr0.states {
+ for prodID := range state.reducible {
+ prod, ok := prods.findByID(prodID)
+ if !ok {
+ return nil, fmt.Errorf("reducible production not found: %v", prodID)
+ }
+
+ flw, err := follow.find(prod.lhs)
+ if err != nil {
+ return nil, err
+ }
+
+ var reducibleItem *lrItem
+ for _, item := range state.items {
+ if item.prod != prodID {
+ continue
+ }
+
+ reducibleItem = item
+ break
+ }
+ if reducibleItem == nil {
+ for _, item := range state.emptyProdItems {
+ if item.prod != prodID {
+ continue
+ }
+
+ reducibleItem = item
+ break
+ }
+ if reducibleItem == nil {
+ return nil, fmt.Errorf("reducible item not found; state: %v, production: %v", state.num, prodID)
+ }
+ }
+
+ if reducibleItem.lookAhead.symbols == nil {
+ reducibleItem.lookAhead.symbols = map[symbol]struct{}{}
+ }
+
+ for sym := range flw.symbols {
+ reducibleItem.lookAhead.symbols[sym] = struct{}{}
+ }
+ if flw.eof {
+ reducibleItem.lookAhead.symbols[symbolEOF] = struct{}{}
+ }
+ }
+ }
+
+ return &slr1Automaton{
+ lr0Automaton: lr0,
+ }, nil
+}