public void IsNullableTest() { var grammar = new Grammar(); var S = grammar.Symbols.Add("S"); var a = grammar.Symbols.Add("a"); var b = grammar.Symbols.Add("b"); var A = grammar.Symbols.Add("A"); var B = grammar.Symbols.Add("B"); grammar.Start = S; grammar.Productions.Define(S, new[] { b, A }); grammar.Productions.Define(A, new[] { a, A, B }); grammar.Productions.Define(A, new Symbol[0]); grammar.Productions.Define(B, new Symbol[0]); var target = new RuntimeGrammar(grammar); Assert.IsTrue(target.IsNullable(A.Index)); Assert.IsTrue(target.IsNullable(B.Index)); Assert.IsFalse(target.IsNullable(a.Index)); Assert.IsFalse(target.IsNullable(b.Index)); Assert.IsFalse(target.IsNullable(S.Index)); }
private void BuildCache() { int tokenCount = grammar.SymbolCount; tokenCache = new SppfNode[tokenCount]; for (int token = 0; token != tokenCount; ++token) { if (grammar.IsNullable(token)) { tokenCache[token] = new SppfNode(token, null, Loc.Unknown, HLoc.Unknown); } } ruleOffsetInCache = new int[grammar.Productions.Count]; ruleEndOffsetInCache = new int[grammar.Productions.Count]; int nullableCount = 0; foreach (var rule in grammar.Productions) { int i = rule.PatternTokens.Length; while (i != 0) { int token = rule.PatternTokens[--i]; if (tokenCache[token] == null) { break; } ++nullableCount; } ruleEndOffsetInCache[rule.Index] = nullableCount; ruleOffsetInCache[rule.Index] = nullableCount - rule.PatternTokens.Length; } this.ruleCache = new SppfNode[nullableCount]; foreach (var rule in grammar.Productions) { int endOffset = ruleOffsetInCache[rule.Index] + rule.PatternTokens.Length; int i = rule.PatternTokens.Length; while (i != 0) { int token = rule.PatternTokens[--i]; if (tokenCache[token] == null) { break; } ruleCache[--endOffset] = tokenCache[token]; } } }
private Msg InternalGetNullable(int nonTerm, IStackLookback <Msg> stackLookback) { Debug.Assert(grammar.IsNullable(nonTerm)); var production = (from r in grammar.GetProductions(nonTerm) where r.PatternTokens.All(grammar.IsNullable) orderby r.PatternTokens.Length ascending select r) .First(); var args = new Msg[production.PatternTokens.Length]; for (int i = 0; i != args.Length; ++i) { args[i] = InternalGetNullable(production.PatternTokens[i], stackLookback); } var value = productionAction(production.Index, args, 0, context, stackLookback); return(new Msg(nonTerm, value, Loc.Unknown)); }