/// <summary> /// constructor, construct parser table /// </summary> public Parser(Grammar grammar) { _lrGotos = new List<int[]>(); _gotoPrecedence = new List<int[]>(); _lr0Items = new List<LR0Item>(); _lr1Items = new List<LR1Item>(); _lr0States = new List<HashSet<int>>(); _lr0Kernels = new List<HashSet<int>>(); _lalrStates = new List<HashSet<int>>(); _terminals = new HashSet<int>(); _nonterminals = new HashSet<int>(); _lalrPropogations = new List<IDictionary<int, IList<LALRPropogation>>>(); _grammar = grammar; _productions = new List<Production>(); _productionDerivation = new List<Derivation>(); _productionPrecedence = new List<int>(); var nTokens = _grammar.TokenCategories.Length; _firstSets = new HashSet<int>[nTokens]; PopulateProductions(); InitSymbols(); GenerateLR0Items(); ComputeFirstSets(); ConvertLR0ItemsToKernels(); var nLalrStates = InitLALRTables(); CalculateLookAheads(); _parseTable = new ParseTable(nLalrStates, nTokens); GenerateParseTable(); }
private static async Task MainAsync(string[] args, CancellationToken token) { // // the following program produces a parse table for the following grammar // for infix expressions, and appropriately applies operator precedence of // the + - * / operators, otherwise evaluating the leftmost operations first // // S' -> e // e -> i // e -> ( e ) // e -> e * e // e -> e / e // e -> e + e // e -> e - e // var grammar = new Grammar( new[] {"S'", "e", "+", "-", "*", "/", "i", "(", ")"}, new PrecedenceGroup(Derivation.None, //S' -> e new Production(0, (_, x) => x[0], 1), //e -> i new Production(1, (_, x) => x.Length == 1 ? x[0] : null, 6), //e -> ( e ) new Production(1, (_, x) => x[1].ContentType == ContentType.Nested ? x[1].Nested : null, 7, 1, 8) ), new PrecedenceGroup(Derivation.LeftMost, //e -> e * e new Production(1, RewriteConstBinaryExpr, 1, 4, 1), //e -> e / e new Production(1, RewriteConstBinaryExpr, 1, 5, 1) ), // productions are left associative and bind less tightly than * or / new PrecedenceGroup(Derivation.LeftMost, //e -> e + e new Production(1, RewriteConstBinaryExpr, 1, 2, 1), //e -> e - e new Production(1, RewriteConstBinaryExpr, 1, 3, 1) ) ); // generate the parse table var parser = new Parser(grammar); var debugger = new Debug(parser, Console.Write, Console.Error.Write); debugger.DumpParseTable(); debugger.Flush(); var parseTime = System.Diagnostics.Stopwatch.StartNew(); #if DEBUG // (24 / 12) + 2 * (3-4) var inputSource = new[] { new Token(6, 2), new Token(2, "+"), new Token(7, "("), new Token(6, 0), new Token(4, "*"), new Token(6, int.MaxValue), new Token(8, ")") }; #else var inputSource = TestLarge(); #endif Token result; using (var tokenIterator = new AsyncLATokenIterator(inputSource.AsAsync())) { result = await parser.ParseInputAsync(tokenIterator, debugger, allowRewriting: true); } parseTime.Stop(); var timeElapsed = string.Format("{0} ms", parseTime.Elapsed.TotalMilliseconds); debugger.WriteFinalToken( string.Format("Accept ({0}): ", timeElapsed), string.Format("Error while parsing ({0}): ", timeElapsed), result); }