/// <summary> /// Gets array of expected currentToken symbols. /// </summary> public ReadOnlyCollection <Symbol> GetExpectedTokens() { List <Symbol> expectedTokens = new List <Symbol>(currentState.ActionCount); #warning Do we need to recurse somehow on non-terminals? for (int i = 0; i < currentState.ActionCount; i++) { switch (currentState.GetAction(i).Symbol.Kind) { case SymbolKind.Terminal: case SymbolKind.End: expectedTokens.Add(currentState.GetAction(i).Symbol); break; } } return(expectedTokens.AsReadOnly()); }
private TokenParseResult ParseToken(Token nextToken) { LalrStateAction stateAction = m_currentLalrState.GetActionBySymbolIndex(nextToken.Symbol.Index); m_tokens.Clear(); if (stateAction != null) { //Work - shift or reduce m_haveReduction = false; //Will be set true if a reduction is made switch (stateAction.Action) { case LalrAction.Accept: m_haveReduction = true; return(TokenParseResult.Accept); case LalrAction.Shift: m_currentLalrState = Grammar.LalrStateTable[stateAction.Value]; nextToken.LalrState = m_currentLalrState; m_stack.Push(nextToken); return(TokenParseResult.Shift); case LalrAction.Reduce: //Produce a reduction - remove as many tokens as members in the rule & push a nonterminal token int ruleIndex = stateAction.Value; Rule currentRule = Grammar.RuleTable[ruleIndex]; //======== Create Reduction Token head; TokenParseResult parseResult; if (TrimReductions && currentRule.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_stack.PopToken(); head.Symbol = currentRule.NonTerminal; parseResult = TokenParseResult.ReduceEliminated; } else { //Build a Reduction m_haveReduction = true; Reduction reduction = new Reduction(currentRule); for (int i = 0; i < currentRule.Count; i++) { reduction.InsertToken(0, m_stack.PopToken()); } head = new Token(currentRule.NonTerminal, reduction); parseResult = TokenParseResult.ReduceNormal; } //========== Goto LalrState nextState = m_stack.PeekToken().LalrState; //========= If nextAction is null here, then we have an Internal Table Error!!!! LalrStateAction nextAction = nextState.GetActionBySymbolIndex(currentRule.NonTerminal.Index); if (nextAction != null) { m_currentLalrState = Grammar.LalrStateTable[nextAction.Value]; head.LalrState = m_currentLalrState; m_stack.Push(head); return(parseResult); } else { return(TokenParseResult.InternalError); } } } else { //=== Syntax Error! Fill Expected Tokens for (int i = 0; i < m_currentLalrState.ActionCount; i++) { switch (m_currentLalrState.GetAction(i).Symbol.SymbolType) { case SymbolType.Terminal: case SymbolType.End: Token token = new Token(m_currentLalrState.GetAction(i).Symbol, "", m_tokenReader.LineNumber); m_tokens.Push(token); break; } } } return(TokenParseResult.SyntaxError); }