/// <summary>Produces a reduction.</summary> /// <remarks>Removes as many tokens as members in the rule and pushes a /// non-terminal token.</remarks> private ParseResult Reduce(Rule p_rule) { ParseResult result; Token head; if (m_trimReductions && p_rule.ContainsOneNonTerminal) { // The current rule only consists of a single nonterminal and can be trimmed from the // parse tree. Usually we create a new Reduction, assign it to the Data property // of Head and push it on the stack. However, in this case, the Data property of the // Head will be assigned the Data property of the reduced token (i.e. the only one // on the stack). In this case, to save code, the value popped of the stack is changed // into the head. head = m_tempStack.PopToken(); head.SetParent(p_rule.RuleNonTerminal); result = ParseResult.ReduceEliminated; } else { Reduction reduction = new Reduction(); reduction.ParentRule = p_rule; m_tempStack.PopTokensInto(reduction, p_rule.SymbolCount); head = new Token(); head.Data = reduction; head.SetParent(p_rule.RuleNonTerminal); m_haveReduction = true; result = ParseResult.ReduceNormal; } int index = m_tempStack.PeekToken().State; LRAction action = m_LalrTables[index].GetActionForSymbol(p_rule.RuleNonTerminal.TableIndex); if (action != null) { head.State = m_LalrState = action.Value;; m_tempStack.PushToken(head); } else { throw new ParserException("Action for LALR state is null"); } return(result); }
/// <summary>Executes a parse-action.</summary> /// <remarks>When this method is called, the parsing engine /// reads information from the source text and then reports what action was taken. /// This ranges from a token being read and recognized from the source, a parse /// reduction, or some type of error.</remarks> public ParseMessage Parse() { while (true) { if (m_inputTokens.Count == 0) { // we must read a token. Token token = RetrieveToken(); if (token == null) { throw new ParserException("RetrieveToken returned null"); } if (token.Kind != SymbolType.Whitespace) { m_inputTokens.PushToken(token); if (m_commentLevel == 0 && !CommentToken(token)) { return(ParseMessage.TokenRead); } } } else if (m_commentLevel > 0) { // we are in a block comment. Token token = m_inputTokens.PopToken(); switch (token.Kind) { case SymbolType.CommentStart: m_commentLevel++; break; case SymbolType.CommentEnd: m_commentLevel--; break; case SymbolType.End: return(ParseMessage.CommentError); } } else { // we are ready to parse. Token token = m_inputTokens.PeekToken(); switch (token.Kind) { case SymbolType.CommentStart: m_inputTokens.PopToken(); m_commentLevel++; break; case SymbolType.CommentLine: m_inputTokens.PopToken(); DiscardLine(); break; default: ParseResult result = ParseToken(token); switch (result) { case ParseResult.Accept: return(ParseMessage.Accept); case ParseResult.InternalError: return(ParseMessage.InternalError); case ParseResult.ReduceNormal: return(ParseMessage.Reduction); case ParseResult.Shift: m_inputTokens.PopToken(); break; case ParseResult.SyntaxError: return(ParseMessage.SyntaxError); } break; } // switch } // else } // while }