public static Automaton CreateAutomaton(Grammar g) { //initialise to closure of start item HashSet<ParseState> states = new HashSet<ParseState>(); states.Add(g.Productions.Where(a => a.Head.Equals(g.Root)).Select(a => new Item(a, 0)).Closure(g)); HashSet<ParseStateTransition> transitions = new HashSet<ParseStateTransition>(); HashSet<ParseState> sToAdd = new HashSet<ParseState>(); HashSet<ParseStateTransition> tToAdd = new HashSet<ParseStateTransition>(); do { sToAdd.Clear(); tToAdd.Clear(); foreach (var state in states) { foreach (var item in state) { if (item.Production.Body.Length == item.Position) continue; BnfTerm term = item.Production.Body[item.Position]; ParseState j = state.Goto(term, g); sToAdd.Add(j); tToAdd.Add(new ParseStateTransition(state, term, j)); } } } while (states.UnionWithAddedCount(sToAdd) != 0 | transitions.UnionWithAddedCount(tToAdd) != 0); return new Automaton(transitions, g); }
public static ParseState Closure(this IEnumerable<Item> items, Grammar grammar) { HashSet<Item> closure = new HashSet<Item>(items); HashSet<Item> toAdd = new HashSet<Item>(); do { toAdd.Clear(); foreach (var item in closure) { if (item.Position == item.Production.Body.Length) continue; BnfTerm term = item.Production.Body[item.Position]; if (term is NonTerminal) { NonTerminal nonTerm = term as NonTerminal; foreach (var production in grammar.Productions.Where(a => a.Head.Equals(nonTerm))) toAdd.Add(new Item(production, 0)); } } } while (closure.UnionWithAddedCount(toAdd) > 0); return new ParseState(closure, IsAcceptingState(closure, grammar)); }
public static Grammar ConstructTestGrammar(out NonTerminal S, out NonTerminal T, out NonTerminal F) { T = new NonTerminal("T"); F = new NonTerminal("F"); T.Rules = T + "*" + F | F; F.Rules = "(" + T + ")" | new Terminal("ID", "([A-Z]|[a-z])+"); var g = new Grammar(T, new Terminal(" ", isIgnored:true)); S = g.Root; return g; }
public void GetFirstSetWithEmptyStrings() { NonTerminal a = new NonTerminal("A"); NonTerminal b = new NonTerminal("B"); a.Rules = b + "s"; b.Rules = "".AsTerminal() | "x"; Grammar g = new Grammar(a); var set = g.GetFirstSet(a); Assert.IsNotNull(set); Assert.AreEqual(2, set.Count); Assert.IsTrue(set.Contains("x")); Assert.IsTrue(set.Contains("s")); }
private IEnumerable<Item> CalculateInitialState(out Grammar g, out NonTerminal S, out NonTerminal T, out NonTerminal F) { S = new NonTerminal("S"); var sCopy = S; T = new NonTerminal("T"); F = new NonTerminal("F"); S.Rules = T + "$"; T.Rules = T + "*" + F | F; F.Rules = "(" + T + ")" | new Terminal("ID", "([A-Z]|[a-z])+"); g = new Grammar(S, new Terminal(" ")); Item start = new Item(g.Productions.First(a => a.Head.Equals(sCopy)), 0); return new[] { start }.Closure(g); }
public static ParseState Goto(this IEnumerable<Item> state, BnfTerm symbol, Grammar grammar) { HashSet<Item> items = new HashSet<Item>(); foreach (var item in state) { if (item.Production.Body.Length == item.Position) continue; BnfTerm term = item.Production.Body[item.Position]; if (term.Equals(symbol)) items.Add(new Item(item.Production, item.Position + 1)); } return items.Closure(grammar); }
public void GetFirstSet() { NonTerminal a = new NonTerminal("A"); NonTerminal b = new NonTerminal("B"); NonTerminal c = new NonTerminal("C"); NonTerminal d = new NonTerminal("D"); a.Rules = b + d | c + d; b.Rules = "b"; c.Rules = "c"; d.Rules = "d"; Grammar g = new Grammar(a); var set = g.GetFirstSet(a); Assert.IsNotNull(set); Assert.AreEqual(2, set.Count); Assert.IsFalse(set.Contains("d")); Assert.IsTrue(set.Contains("b")); Assert.IsTrue(set.Contains("c")); }
public void ConstructAGrammar() { NonTerminal op = new NonTerminal("Operator"); NonTerminal expr = new NonTerminal("Expression"); Terminal number = new Terminal("Number", @"\b\d+\b"); Terminal plus = new Terminal("Plus", @"\+"); Terminal multiply = @"\*"; op.Rules = plus | multiply; expr.Rules = number + op + expr; Terminal whitespace = new Terminal("Whitespace", " |\n|\r", true); Grammar g = new Grammar(expr, whitespace); Assert.AreEqual(3, g.Terminals.Count()); Assert.AreEqual(3, g.NonTerminals.Count()); //Although the grammar only specifies 2 Nonterminals, grammar creates 1 internally for the root Lexer lexer = g.CreateLexer("1 + 2 * 3"); Assert.AreEqual(5, lexer.Count()); }
public Automaton(IEnumerable<ParseStateTransition> transitions, Grammar grammar) { this.grammar = grammar; foreach (var transition in transitions) { allStates.Add(transition.Start); allStates.Add(transition.End); Dictionary<BnfTerm, ParseState> d; if (!transitionRules.TryGetValue(transition.Start, out d)) { d = new Dictionary<BnfTerm, ParseState>(); transitionRules.Add(transition.Start, d); } if (d.ContainsKey(transition.Trigger)) throw new InvalidOperationException("Duplicate transition"); d[transition.Trigger] = transition.End; } }
public void GetFollowSet() { NonTerminal a = new NonTerminal("A"); NonTerminal b = new NonTerminal("B"); a.Rules = "a" + b; b.Rules = b + "a" | "c"; Grammar g = new Grammar(a); var followA = g.GetFollowSet(a); Assert.AreEqual(0, followA.Count); var followB = g.GetFollowSet(b); Assert.AreEqual(1, followB.Count); Assert.IsTrue(followB.Contains("a")); }
public void IsNullable() { NonTerminal a = new NonTerminal("A"); NonTerminal b = new NonTerminal("B"); NonTerminal c = new NonTerminal("C"); a.Rules = b + "s"; b.Rules = "".AsTerminal() | c; c.Rules = "c"; Grammar g = new Grammar(a); Assert.IsTrue(b.IsNullable); Assert.IsFalse(a.IsNullable); Assert.IsFalse(c.IsNullable); }
public RecursiveDescentParser(Grammar g) : base(g) { ConstructPredictiveParseTable(); }
public Parser(Grammar grammar) { Grammar = grammar; }
public static bool IsAcceptingState(this IEnumerable<Item> items, Grammar grammar) { return items .Where(a => a.Production.Head.Equals(grammar.Root)) .Any(a => a.Position == a.Production.Body.Length); }
public SLR1(Grammar grammar) : base(grammar) { }
private ParseState MakeStateState(NonTerminal root, Grammar g) { return new HashSet<Item>(root.Rules.Select(a => new Item(new Production(root, a), 0))).Closure(g); }
public LRParserBase(Grammar g) : base(g) { }
public LR0(Grammar grammar) : base(grammar) { automaton = CreateAutomaton(grammar); }