/// <summary> /// Raises an error on an unexepcted token /// </summary> /// <param name="stem">The size of the generation's stem</param> private void OnUnexpectedToken(int stem) { // build the list of expected terminals List <Symbol> expected = new List <Symbol>(); GSSGeneration genData = gss.GetGeneration(); for (int i = 0; i != genData.Count; i++) { LRExpected expectedOnHead = parserAutomaton.GetExpected(gss.GetRepresentedState(i + genData.Start), lexer.Terminals); // register the terminals for shift actions foreach (Symbol terminal in expectedOnHead.Shifts) { if (!expected.Contains(terminal)) { expected.Add(terminal); } } if (i < stem) { // the state was in the stem, also look for reductions foreach (Symbol terminal in expectedOnHead.Reductions) { if (!expected.Contains(terminal) && CheckIsExpected(i + genData.Start, terminal)) { expected.Add(terminal); } } } } // register the error UnexpectedTokenError error = new UnexpectedTokenError(lexer.tokens[nextToken.Index], new ROList <Symbol>(expected)); allErrors.Add(error); #if !NETSTANDARD1_0 if (ModeDebug) { Console.WriteLine("==== RNGLR parsing error:"); Console.Write("\t"); Console.WriteLine(error); TextContext context = lexer.Input.GetContext(error.Position); Console.Write("\t"); Console.WriteLine(context.Content); Console.Write("\t"); Console.WriteLine(context.Pointer); gss.Print(); } #endif }
/// <summary> /// Raises an error on an unexpected token /// </summary> /// <param name="kernel">The unexpected token's kernel</param> /// <returns>The next token kernel in the case the error is recovered</returns> private Lexer.TokenKernel OnUnexpectedToken(Lexer.TokenKernel kernel) { LRExpected expectedOnHead = automaton.GetExpected(stack[head], lexer.Terminals); // the terminals for shifts are always expected List <Symbol> expected = new List <Symbol>(expectedOnHead.Shifts); // check the terminals for reductions foreach (Symbol terminal in expectedOnHead.Reductions) { if (CheckIsExpected(terminal)) { expected.Add(terminal); } } // register the error allErrors.Add(new UnexpectedTokenError(lexer.tokens[kernel.Index], new ROList <Symbol>(expected))); // TODO: try to recover, or not return(new Lexer.TokenKernel(Symbol.SID_NOTHING, -1)); }
/// <summary> /// Gets the expected terminals for the specified state /// </summary> /// <param name="state">The DFA state</param> /// <param name="terminals">The possible terminals</param> /// <returns>The expected terminals</returns> public LRExpected GetExpected(int state, ROList <Symbol> terminals) { LRExpected result = new LRExpected(); int offset = ncols * state; for (int i = 0; i != terminals.Count; i++) { LRAction action = table[offset]; if (action.Code == LRActionCode.Shift) { result.Shifts.Add(terminals[i]); } else if (action.Code == LRActionCode.Reduce) { result.Reductions.Add(terminals[i]); } offset++; } return(result); }
/// <summary> /// Gets the expected terminals for the specified state /// </summary> /// <param name="state">The DFA state</param> /// <param name="terminals">The possible terminals</param> /// <returns>The expected terminals</returns> public LRExpected GetExpected(int state, ROList <Symbol> terminals) { LRExpected result = new LRExpected(); for (int i = 0; i != terminals.Count; i++) { Cell cell = table[state * ncols + i]; for (int j = 0; j != cell.ActionsCount; j++) { LRAction action = actions[cell.ActionsIndex + j]; if (action.Code == LRActionCode.Shift) { result.AddUniqueShift(terminals[i]); } else if (action.Code == LRActionCode.Reduce) { result.AddUniqueReduction(terminals[i]); } } } return(result); }