protected internal virtual ParserAction GetNextAction() { var currState = Context.CurrentParserState; var currInput = Context.CurrentParserInput; if (currState.DefaultAction != null) { return(currState.DefaultAction); } ParserAction action; //First try as keyterm/key symbol; for example if token text = "while", then first try it as a keyword "while"; // if this does not work, try as an identifier that happens to match a keyword but is in fact identifier Token inputToken = currInput.Token; if (inputToken != null && inputToken.KeyTerm != null) { var keyTerm = inputToken.KeyTerm; if (currState.Actions.TryGetValue(keyTerm, out action)) { #region comments // Ok, we found match as a key term (keyword or special symbol) // Backpatch the token's term. For example in most cases keywords would be recognized as Identifiers by Scanner. // Identifier would also check with SymbolTerms table and set AsSymbol field to SymbolTerminal if there exist // one for token content. So we first find action by Symbol if there is one; if we find action, then we // patch token's main terminal to AsSymbol value. This is important for recognizing keywords (for colorizing), // and for operator precedence algorithm to work when grammar uses operators like "AND", "OR", etc. //TODO: This might be not quite correct action, and we can run into trouble with some languages that have keywords that // are not reserved words. But proper implementation would require substantial addition to parser code: // when running into errors, we need to check the stack for places where we made this "interpret as Symbol" // decision, roll back the stack and try to reinterpret as identifier #endregion inputToken.SetTerminal(keyTerm); currInput.Term = keyTerm; currInput.Precedence = keyTerm.Precedence; currInput.Associativity = keyTerm.Associativity; return(action); } } //Try to get by main Terminal, only if it is not the same as symbol if (currState.Actions.TryGetValue(currInput.Term, out action)) { return(action); } //If input is EOF and NewLineBeforeEof flag is set, try using NewLine to find action if (currInput.Term == _grammar.Eof && _grammar.LanguageFlags.IsSet(LanguageFlags.NewLineBeforeEOF) && currState.Actions.TryGetValue(_grammar.NewLine, out action)) { //There's no action for EOF but there's action for NewLine. Let's add newLine token as input, just in case // action code wants to check input - it should see NewLine. var newLineToken = new Token(_grammar.NewLine, currInput.Token.Location, "\r\n", null); var newLineNode = new ParseTreeNode(newLineToken) { Tokens = Context.ComputeTokenSubList() }; Context.CurrentParserInput = newLineNode; return(action); }//if return(null); }
private void CheckReservedWord(Token token) { if (!Grammar.KeyTerms.TryGetValue(token.Text, out KeyTerm keyTerm)) { return; } token.KeyTerm = keyTerm; //if it is reserved word, then overwrite terminal if (keyTerm.Flags.IsSet(TermFlags.IsReservedWord)) { token.SetTerminal(keyTerm); } }