private ParserNode CreateNode(ParserContext context) { var node = new ParserNode(context, Reduction.Product); node.Children.AddRange(PopChildren(context).Reverse()); node.EnsureResultComputed(); return node; }
public ParseResult Parse(Lexer lexer, ParserState initialState) { var context = new ParserContext(this, Automaton.Grammar, lexer); context.CurrentState = initialState; context.ParserStack.Push(new ParserNode(context, new GrammarDefinition("init")) { State = initialState }); ReadNextToken(context); context.CurrentNode = new ParserNode(context, Automaton.Grammar.ToElement(lexer.Current.GetTokenCode()), lexer.Current); while (lexer.Current != null && context.Root == null && context.CurrentState != null) { // If no input and no default action (e.g. a grammar reduction), // that means we have to read the next token. if (context.CurrentNode == null && context.CurrentState.DefaultAction == null) ReadNextToken(context); var action = GetNextAction(context); action.Execute(context); } lexer.SpecialBag.InsertNodesIntoAstNode(context.Root.Result); return ParseResult.FromContext(context); }
public override void Execute(ParserContext context) { context.SendLogMessage(MessageSeverity.Message, ToString()); CustomAction?.Invoke(context); context.ParserStack.Push(context.CurrentNode); context.CurrentState = context.CurrentNode.State = NextState; context.CurrentNode = null; }
public override void Execute(ParserContext context) { context.SendLogMessage(MessageSeverity.Message, ToString()); context.Root = context.ParserStack.Pop(); context.CurrentNode = null; context.CurrentState = context.ParserStack.Peek().State; }
public override void Execute(ParserContext context) { ReportSyntaxError(context); if (!TryRecover(context)) { context.SendLogMessage(MessageSeverity.Error, "Failed to recover from syntax error."); context.CurrentState = null; } }
private static void ReportSyntaxError(ParserContext context) { var expectedTokens = context.CurrentState.Actions.Keys.OfType<TokenGrammarElement>().ToArray(); var node = context.CurrentNode; var message = string.Format("Unexpected {0} token. Expected {1}.", node.GrammarElement.Name, string.Join(" or ", expectedTokens.Select(x => x.Name))); context.SyntaxErrors.Add(new SyntaxError(node.Result.Range.Start, message, MessageSeverity.Error)); context.SendLogMessage(MessageSeverity.Error, message); }
public override void Execute(ParserContext context) { context.SendLogMessage(MessageSeverity.Message, ToString()); var temp = context.CurrentNode; var node = context.CurrentNode = CreateNode(context); context.CurrentState = context.ParserStack.Peek().State; var action = context.CurrentState.Actions[node.GrammarElement]; action.Execute(context); context.CurrentNode = temp; }
public ParserAction GetNextAction(ParserContext context) { if (context.CurrentState.DefaultAction != null) return context.CurrentState.DefaultAction; ParserAction parserAction; if (!context.CurrentState.Actions.TryGetValue(context.CurrentNode.GrammarElement, out parserAction)) { // Unexpected token or grammar pattern. Try to recover. return ErrorParserAction.Instance; } return parserAction; }
private static ShiftParserAction PopToErrorShifter(ParserContext context) { ParserAction action = null; while (context.ParserStack.Any()) { var state = context.ParserStack.Peek().State; context.SendLogMessage(MessageSeverity.Message, "Going back to state " + state.Id + "."); state.Actions.TryGetValue(Grammar.Error, out action); if (action is ShiftParserAction) break; context.ParserStack.Pop(); } return action as ShiftParserAction; }
private static bool TryRecover(ParserContext context) { // Find shifter for error token, or fail recovery. var errorShifter = PopToErrorShifter(context); if (errorShifter == null) return false; // Execute shift. var currentNode = context.CurrentNode; context.CurrentNode = new ParserNode(context, Grammar.Error); errorShifter.Execute(context); context.CurrentNode = currentNode; while (true) { if (context.CurrentNode == null && context.CurrentState.DefaultAction == null) context.Parser.ReadNextToken(context); var action = context.Parser.GetNextAction(context); // Discard tokens until legal action can be made. if (action is ErrorParserAction) { if (context.CurrentNode.GrammarElement == Grammar.Eof) return false; context.Parser.ReadNextToken(context); } else { action.Execute(context); } // If we found a synchronize token (i.e. a reduction with an error token), we have recovered. if (action is ReduceParserAction) return true; } }
private void WarningEmptyStatement(ParserContext context, TextLocation location) { context.SyntaxErrors.Add(new SyntaxError(location, "Possible mistaken empty statement.", MessageSeverity.Warning)); }
public abstract void Execute(ParserContext context);
public static ParseResult FromContext(ParserContext context) { return new ParseResult(context.Root, context.SyntaxErrors); }
private IEnumerable<ParserNode> PopChildren(ParserContext context) { var childCount = Reduction.Sequence.Count; for (int i = 0; i < childCount; i++) yield return context.ParserStack.Pop(); }
internal void SendLogMessage(ParserContext parserContext, MessageSeverity severity, string message) { if (EnableLogging) LogMessageReceived?.Invoke(this, new SourceParserLogEventArgs(parserContext, severity, message)); }
public void ReadNextToken(ParserContext context) { context.SendLogMessage(MessageSeverity.Message, "Read next token."); var lexer = context.Lexer; lexer.Advance(); context.CurrentNode = new ParserNode(context, Automaton.Grammar.ToElement(lexer.Current.GetTokenCode()), lexer.Current); }
public SourceParserLogEventArgs(ParserContext parserContext, MessageSeverity messageSeverity, string message) { ParserContext = parserContext; MessageSeverity = messageSeverity; Message = message; }