func SplitLR0State(newid int, state *LR0State, filter Lr0ItemFilterFn, transform Lr0ItemTransformFn) *LR0State { filterItems := tree.NewTree() addItems := tree.NewTree() for x := state.items.First(); x.HasNext(); { it := x.Next().(*LR0Item) if filter(it) { filterItems.Insert(it) } ni := transform(it) if ni != nil { addItems.Insert(ni) } } if filterItems.Size() == 0 && addItems.Size() == 0 { return nil } for x := filterItems.First(); x.HasNext(); { state.items.Delete(x.Next().(*LR0Item)) } for x := addItems.First(); x.HasNext(); { filterItems.Insert(x.Next().(*LR0Item)) } newState := &LR0State{id: newid, items: filterItems} return newState }
func BuildDfa(g parser.Grammar, passEpsilons bool) (*LR0Dfa, error) { nextId := 1 ig := parser.GetIndexedGrammar(g) idx, err := ig.GetIndex(index.GRAMMAR_CLASS_INDEX) if err != nil { return nil, err } gcidx := idx.(*index.GrammarClassIndex) if !gcidx.Class().ContextFree() { return nil, errors.New("cannot create lr0 dfa for a non-context-free grammar") } idx, err = ig.GetIndex(index.BASIC_INDEX) if err != nil { return nil, err } bidx := idx.(*index.BasicGrammarIndex) canon := tree.NewTree() start := bidx.LhsStart(ig.Asterisk(), 0) initState := &LR0State{id: 0, items: tree.NewTree(), transitions: make(map[parser.GrammarParticle]*LR0State)} initState.items.Insert(InitialLR0Item(start)) CloseLR0State(initState, ig, passEpsilons) canon.Insert(initState) newStates := tree.NewTree() newStates.Insert(initState) for newStates.Size() > 0 { ns := newStates.First().Next().(*LR0State) newStates.Delete(ns) if MakeTransitions(ns, ig) != nil { return nil, err } for part, next := range ns.transitions { CloseLR0State(next, ig, passEpsilons) if cn, has := canon.Lookup(c.LTE, next); has { next = cn.(*LR0State) } else { next.id = nextId nextId++ canon.Insert(next) newStates.Insert(next) } ns.transitions[part] = next } } dfa := &LR0Dfa{} dfa.states = make([]*LR0State, nextId) for x := canon.First(); x.HasNext(); { sx := x.Next().(*LR0State) dfa.states[sx.id] = sx } return dfa, nil }
func (ts *treeSet) Difference(s Set) Set { nt := tree.NewTree() c := ts.OpenCursor() for c.HasNext() { k := c.Next() if !s.Contains(k) { nt.Insert(k) } } return TreeSet(nt) }
func OpenGrammarBuilder() *GrammarBuilder { gb := &GrammarBuilder{ nonterms: make(map[string]GrammarParticle), terms: make(map[string]GrammarParticle), rules: tree.NewTree(), actions: make(map[Production]ValueFunction), } gb.epsilon = &GenericEpsilon{} gb.asterisk = &GenericAsterisk{} gb.bottom = &GenericBottom{} return gb }
func (ts *treeSet) Union(s Set) Set { nt := tree.NewTree() tsc := ts.OpenCursor() for tsc.HasNext() { nt.Insert(tsc.Next()) } sc := s.OpenCursor() for sc.HasNext() { nt.Insert(sc.Next()) } return TreeSet(nt) }
func (ps *pairSet) Union(s Set) Set { t := tree.NewTree() t.Insert(ps.x) t.Insert(ps.y) c := s.OpenCursor() for c.HasNext() { t.Insert(c.Next()) } if t.Size() == 2 { return ps } return &treeSet{tree: t} }
func (ts *treeSet) Intersection(s Set) Set { if ts.Size() > s.Size() { return s.Intersection(ts) } nt := tree.NewTree() c := ts.OpenCursor() for c.HasNext() { k := c.Next() if s.Contains(k) { nt.Insert(k) } } return TreeSet(nt) }
// XXX - This should have an option to forward over nihilistic carets. func MakeTransitions(ci *LR0State, g *parser.IndexedGrammar) error { fmt.Println("MAKE TRS: " + ci.String()) tmap := make(map[parser.GrammarParticle]*LR0State) rmap := make(map[parser.GrammarParticle]map[parser.Production]bool) for x := ci.items.First(); x.HasNext(); { xi := x.Next().(*LR0Item) if !xi.HasNext() { nt := xi.Production().Lhs(0) if _, has := rmap[nt]; !has { rmap[nt] = make(map[parser.Production]bool) } rmap[nt][xi.Production()] = true } else { tt := xi.Caret() if _, has := tmap[tt]; !has { tmap[tt] = &LR0State{items: tree.NewTree()} } tmap[tt].items.Insert(xi.Next()) } } if ci.transitions == nil { ci.transitions = tmap } else { for k, v := range tmap { ci.transitions[k] = v } } if ci.reductions == nil { ci.reductions = make(map[parser.GrammarParticle][]parser.Production) } for part, pmap := range rmap { if _, has := ci.reductions[part]; !has { ci.reductions[part] = make([]parser.Production, 0, len(pmap)) } for prod, _ := range pmap { ci.reductions[part] = append(ci.reductions[part], prod) } } return nil }
func CloseLR0State(s *LR0State, g *parser.IndexedGrammar, forwardEpsilons bool) (bool, error) { var changed bool fmt.Println("CLOSE: " + s.String()) idx, err := g.GetIndex(index.BASIC_INDEX) if err != nil { return false, err } seennt := tree.NewTree() bidx := idx.(*index.BasicGrammarIndex) newItems := make([]*LR0Item, 0, s.items.Size()) for cr := s.items.First(); cr.HasNext(); { newItems = append(newItems, cr.Next().(*LR0Item)) } for len(newItems) > 0 { ci := newItems[len(newItems)-1] newItems = newItems[0 : len(newItems)-1] if _, has := s.items.Lookup(c.LTE, ci); !has { s.items.Insert(ci) changed = true } if !ci.HasNext() { continue } at := ci.Caret() if !(at.Nonterminal() || at.Asterisk()) { continue } if forwardEpsilons && bidx.Epsilon(at) { ni := ci.Next() if !ni.HasNext() { // spurious epsilon reduction nt := ni.Production().Lhs(0) if s.reductions == nil { s.reductions = make(map[parser.GrammarParticle][]parser.Production) } if _, has := s.reductions[nt]; !has { s.reductions[nt] = make([]parser.Production, 0, 1) } var has bool for _, k := range s.reductions[nt] { if k.CompareTo(ni.Production()) == 0 { has = true break } } if !has { s.reductions[nt] = append(s.reductions[nt], ni.Production()) } } newItems = append(newItems, ni) } if _, has := seennt.Lookup(c.LTE, at); has { continue } seennt.Insert(at) for i := 0; i < bidx.NumLhsStarts(at); i++ { newItems = append(newItems, InitialLR0Item(bidx.LhsStart(at, i))) } } return changed, nil }
func SeedState(id int, p parser.Production) *LR0State { state := LR0State{id: id, items: tree.NewTree(), transitions: make(map[parser.GrammarParticle]*LR0State)} state.items.Insert(InitialLR0Item(p)) return &state }
func (ff *FFIndex) Initialize(g parser.Grammar) error { ff.grammar = g index := parser.GetIndexedGrammar(g) idx, err := index.GetIndex(GRAMMAR_CLASS_INDEX) if err != nil { return err } cidx := idx.(*GrammarClassIndex) if cidx.Class() >= parser.CONTEXT_SENSITIVE { return errors.New("cannot first/follow index a non-context-free grammar") } idx, err = index.GetIndex(BASIC_INDEX) bidx := idx.(*BasicGrammarIndex) if err != nil { return err } // FIRST set calculation ff.firstSets = make(map[parser.GrammarParticle][]parser.GrammarParticle) for _, nt := range index.Nonterminals() { fs := tree.NewTree() ntseen := tree.NewTree() ntpending := []parser.GrammarParticle{nt} for len(ntpending) > 0 { cnt := ntpending[0] ntpending = ntpending[1:] for i := 0; i < bidx.NumLhsStarts(cnt); i++ { p := bidx.LhsStart(cnt, i) for j := 0; j < p.RhsLen(); j++ { rt := p.Rhs(j) if rt.Terminal() { fs.Insert(rt) break } else if rt.Nonterminal() { if _, has := ntseen.Lookup(c.LTE, rt); !has { ntseen.Insert(rt) fs.Insert(rt) ntpending = append(ntpending, rt) } if !bidx.Epsilon(rt) { break } } else { break } } } } ff.firstSets[nt] = make([]parser.GrammarParticle, 0, fs.Size()) for c := fs.First(); c.HasNext(); { ff.firstSets[nt] = append(ff.firstSets[nt], c.Next().(parser.GrammarParticle)) } } // LAST set calculation ff.lastSets = make(map[parser.GrammarParticle][]parser.GrammarParticle) for _, nt := range index.Nonterminals() { fs := tree.NewTree() ntseen := tree.NewTree() ntpending := []parser.GrammarParticle{nt} for len(ntpending) > 0 { cnt := ntpending[0] ntpending = ntpending[1:] for i := 0; i < bidx.NumLhsStarts(cnt); i++ { p := bidx.LhsStart(cnt, i) for j := p.RhsLen() - 1; j >= 0; j-- { rt := p.Rhs(j) if rt.Terminal() { fs.Insert(rt) break } if rt.Nonterminal() { if _, has := ntseen.Lookup(c.LTE, rt); !has { ntseen.Insert(rt) fs.Insert(rt) ntpending = append(ntpending, rt) if !bidx.Epsilon(rt) { break } } } } } } ff.lastSets[nt] = make([]parser.GrammarParticle, 0, fs.Size()) for c := fs.First(); c.HasNext(); { ff.lastSets[nt] = append(ff.lastSets[nt], c.Next().(parser.GrammarParticle)) } } // IN set calculation ff.inSets = make(map[parser.GrammarParticle][]parser.GrammarParticle) for _, nt := range index.Nonterminals() { fs := tree.NewTree() ntseen := tree.NewTree() ntpending := []parser.GrammarParticle{nt} for len(ntpending) > 0 { cnt := ntpending[0] ntpending = ntpending[1:] for i := 0; i < bidx.NumLhsStarts(cnt); i++ { p := bidx.LhsStart(cnt, i) for j := p.RhsLen() - 1; j >= 0; j-- { rt := p.Rhs(j) if rt.Terminal() { fs.Insert(rt) } if rt.Nonterminal() { if _, has := ntseen.Lookup(c.LTE, rt); !has { ntseen.Insert(rt) fs.Insert(rt) ntpending = append(ntpending, rt) } } } } } ff.inSets[nt] = make([]parser.GrammarParticle, 0, fs.Size()) for c := fs.First(); c.HasNext(); { ff.inSets[nt] = append(ff.inSets[nt], c.Next().(parser.GrammarParticle)) } } // FOLLOW set calculation followRefs := make(map[parser.GrammarParticle]tree.Tree) followSets := make(map[parser.GrammarParticle]tree.Tree) for _, p := range g.Productions() { // First-pass. for i := 0; i < p.RhsLen()-1; i++ { for j := i + 1; j < p.RhsLen(); j++ { if _, has := followSets[p.Rhs(i)]; !has { followSets[p.Rhs(i)] = tree.NewTree() } followSets[p.Rhs(i)].Insert(p.Rhs(j)) if !bidx.Epsilon(p.Rhs(j)) { break } } } tp := p.Rhs(p.RhsLen() - 1) if _, has := followRefs[tp]; !has { followRefs[tp] = tree.NewTree() } followRefs[tp].Insert(p.Lhs(0)) } var changed bool = true for changed { // Take closure. changed = false for p, prt := range followRefs { for cr := prt.First(); cr.HasNext(); { fp := cr.Next().(parser.GrammarParticle) // x in Follow(fp) -> x in Follow(p) if fromSet, has := followSets[fp]; has { if _, has := followSets[p]; !has { followSets[p] = tree.NewTree() } for k := fromSet.First(); k.HasNext(); { x := k.Next().(parser.GrammarParticle) if _, has := followSets[p].Lookup(c.LTE, x); !has { changed = true followSets[p].Insert(x) } } } } } } ff.followSets = make(map[parser.GrammarParticle][]parser.GrammarParticle) for r, v := range followSets { // Collect results. ff.followSets[r] = make([]parser.GrammarParticle, 0, v.Size()) for c := v.First(); c.HasNext(); { ff.followSets[r] = append(ff.followSets[r], c.Next().(parser.GrammarParticle)) } } return nil }
func BuildEpsilonLR0Dfa(g parser.Grammar) (*Elr0Dfa, error) { ig := parser.GetIndexedGrammar(g) idx, err := ig.GetIndex(index.BASIC_INDEX) if err != nil { return nil, err } bidx := idx.(*index.BasicGrammarIndex) idx, err = ig.GetIndex(index.GRAMMAR_CLASS_INDEX) if err != nil { return nil, err } cidx := idx.(*index.GrammarClassIndex) if !cidx.Class().ContextFree() { return nil, errors.New("cannot build an ε-lr0 dfa for a non-context-free grammar") } advanceIndexForward := func(item *lr0.LR0Item) *lr0.LR0Item { if !item.HasNext() { return nil } if bidx.Epsilon(item.Caret()) { return item.Next() } return nil } canon := tree.NewTree() newStates := tree.NewTree() nextId := 1 start := bidx.LhsStart(ig.Asterisk(), 0) initState := lr0.SeedState(0, start) lr0.CloseLR0State(initState, ig, false) eInit := lr0.SplitLR0State(nextId, initState, advanceIndexSelect, advanceIndexForward) if eInit != nil { //nextId++ Tweaky juggling... this is the first new id, we want to use #1 lr0.CloseLR0State(eInit, ig, true) lr0.SetTransition(initState, eInit, ig.Epsilon()) } canon.Insert(initState) newStates.Insert(initState) // if eInit != nil { // canon.Insert(eInit) // newStates.Insert(eInit) // } fmt.Println("INIT STATE: " + initState.String()) fmt.Println("INIT-e STATE: " + eInit.String()) for newStates.Size() > 0 { fmt.Printf("NS LEN: %d\n", newStates.Size()) cs := newStates.First().Next().(*lr0.LR0State) _, has := newStates.Delete(cs) if !has { fmt.Println("LOOKING AT " + cs.String()) tree.DumpTree(newStates.(*tree.AvlTree)) panic("FAILED DELETE") } fmt.Printf("NS LEN after del : %d\n", newStates.Size()) fmt.Println("TOOK STATE: " + cs.String()) if lr0.MakeTransitions(cs, ig) != nil { return nil, err } for part, next := range lr0.GetTransitions(cs) { fmt.Println("A") lr0.CloseLR0State(next, ig, false) if nxt, has := canon.Lookup(c.LTE, next); has { next = nxt.(*lr0.LR0State) lr0.SetTransition(cs, next, part) continue } if !part.Epsilon() { fmt.Println("B?") eNext := lr0.SplitLR0State(nextId, next, advanceIndexSelect, advanceIndexForward) if eNext == nil { fmt.Println("B-") canon.Insert(next) newStates.Insert(next) lr0.AssignId(next, nextId) nextId++ continue } fmt.Println("B+") lr0.CloseLR0State(eNext, ig, true) if nxt, has := canon.Lookup(c.LTE, eNext); has { eNext = nxt.(*lr0.LR0State) } else { canon.Insert(eNext) newStates.Insert(eNext) nextId++ } if nxt, has := canon.Lookup(c.LTE, next); has { next = nxt.(*lr0.LR0State) } else { canon.Insert(next) newStates.Insert(next) lr0.AssignId(next, nextId) nextId++ } lr0.SetTransition(next, eNext, ig.Epsilon()) } else { if nxt, has := canon.Lookup(c.LTE, next); has { next = nxt.(*lr0.LR0State) } else { canon.Insert(next) newStates.Insert(next) lr0.AssignId(next, nextId) nextId++ } lr0.SetTransition(cs, next, part) } } } dfa := &Elr0Dfa{} dfa.states = make([]*lr0.LR0State, nextId) for x := canon.First(); x.HasNext(); { sx := x.Next().(*lr0.LR0State) dfa.states[sx.Id()] = sx } return dfa, nil }
func (ts *treeSet) Clear() { ts.tree = tree.NewTree() }