From e110a6ff4073799d00c7d3400ac022f758a03e40 Mon Sep 17 00:00:00 2001 From: Ryo Nihei Date: Wed, 18 Aug 2021 00:03:59 +0900 Subject: Set look-ahead symbols to items before generating a SLR(1) parsing table --- grammar/slr1.go | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 grammar/slr1.go (limited to 'grammar/slr1.go') 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 +} -- cgit v1.2.3