Example #1
0
File: lr0.go Project: dtromb/parser
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
}
Example #2
0
File: lr0.go Project: dtromb/parser
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
}
Example #3
0
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)
}
Example #4
0
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
}
Example #5
0
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)
}
Example #6
0
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}
}
Example #7
0
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)
}
Example #8
0
File: lr0.go Project: dtromb/parser
// 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
}
Example #9
0
File: lr0.go Project: dtromb/parser
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
}
Example #10
0
File: lr0.go Project: dtromb/parser
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
}
Example #11
0
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
}
Example #12
0
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
}
Example #13
0
func (ts *treeSet) Clear() {
	ts.tree = tree.NewTree()
}