private bool DoReduction(Stack <Token> tokenStack, LookAheadBuffer lookAheadBuffer, ref ushort lalrState, LRAction parseAction) { Token head = null; //Produce a reduction - remove as many tokens as members in the rule & push a nonterminal token Production prod = egtDataManager.GetProduction(parseAction.Value); bool reductionSkipped = false; //Skip reduction? if ((TrimReductions && prod.ConsistsOfOneNonTerminal()) || (SkipEmptyProductions && prod.Handle.Count == 0)) { head = tokenStack.Pop(); head.Symbol = prod.Head; reductionSkipped = true; } //Build a Reduction else { Reduction reduction = new Reduction(prod.Handle.Count, prod); //If a production has no handles, it has no location. //Set a would-be location instead. if (prod.Handle.Count == 0) { reduction.StartPosition = reduction.EndPosition = lookAheadBuffer.Position; } else { for (int i = prod.Handle.Count - 1; i >= 0; i--) { reduction[i] = tokenStack.Pop(); } } head = reduction; } //If n is -1 here, then we have an Internal Table Error!!! LRAction action = egtDataManager.GetLRActionList(tokenStack.Peek().State)[prod.Head]; if (action == null) { OnInternalError(); return(false); } lalrState = action.Value; head.State = lalrState; tokenStack.Push(head); if (!reductionSkipped) { OnReduction((Reduction)tokenStack.Peek()); } return(true); }
// This function analyzes a token and either: // 1. Makes a SINGLE reduction and pushes a complete Reduction object on the m_Stack // 2. Accepts the token and shifts // 3. Errors and places the expected symbol indexes in the Tokens list // The Token is assumed to be valid and WILL be checked // If an action is performed that requires controlt to be returned to the user, the function returns true. // The Message parameter is then set to the type of action. private ParseResult ParseLALR(ref Token token) { LRAction parseAction = lrStates[currentLALR][token.Parent]; ParseResult parseResult = 0; if (parseAction != null) { haveReduction = false; switch (parseAction.Type) { case LRActionType.Shift: currentLALR = parseAction.Value; token.State = (short)currentLALR; stack.Push(token); parseResult = ParseResult.Shift; break; case LRActionType.Reduce: Production production = ProductionTable[parseAction.Value]; Token head; // 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 m_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 m_Stack). // In this case, to save code, the value popped of the m_Stack is changed into the head. if (TrimReductions && production.ContainsOneNonTerminal()) { head = stack.Pop(); head.Parent = production.Head; parseResult = ParseResult.ReduceEliminated; } else { haveReduction = true; Reduction newReduction = new Reduction(production.Handle.Count()) { Parent = production }; short n = (short)(production.Handle.Count() - 1); while (n >= 0) { newReduction[n] = stack.Pop(); n--; } head = new Token(production.Head, newReduction); parseResult = ParseResult.ReduceNormal; } short index = stack.Peek().State; short n2 = lrStates[index].IndexOf(production.Head); if (n2 != -1) { currentLALR = lrStates[index][n2].Value; head.State = (short)currentLALR; stack.Push(head); break; } parseResult = ParseResult.InternalError; break; case LRActionType.Accept: haveReduction = true; parseResult = ParseResult.Accept; break; } } else { ExpectedSymbols.Clear(); foreach (LRAction LRAction in lrStates[currentLALR]) { switch (LRAction.Symbol.Type) { case SymbolType.Content: case SymbolType.End: case SymbolType.GroupStart: case SymbolType.GroupEnd: ExpectedSymbols.Add(LRAction.Symbol); break; } } parseResult = ParseResult.SyntaxError; } return(parseResult); }
private bool DoReduction(Stack<Token> tokenStack, LookAheadBuffer lookAheadBuffer, ref ushort lalrState, LRAction parseAction) { Token head = null; //Produce a reduction - remove as many tokens as members in the rule & push a nonterminal token Production prod = egtDataManager.GetProduction(parseAction.Value); bool reductionSkipped = false; //Skip reduction? if ((TrimReductions && prod.ConsistsOfOneNonTerminal()) || (SkipEmptyProductions && prod.Handle.Count == 0)) { head = tokenStack.Pop(); head.Symbol = prod.Head; reductionSkipped = true; } //Build a Reduction else { Reduction reduction = new Reduction(prod.Handle.Count, prod); //If a production has no handles, it has no location. //Set a would-be location instead. if (prod.Handle.Count == 0) { reduction.StartPosition = reduction.EndPosition = lookAheadBuffer.Position; } else { for (int i = prod.Handle.Count - 1; i >= 0; i--) { reduction[i] = tokenStack.Pop(); } } head = reduction; } //If n is -1 here, then we have an Internal Table Error!!! LRAction action = egtDataManager.GetLRActionList(tokenStack.Peek().State)[prod.Head]; if (action == null) { OnInternalError(); return false; } lalrState = action.Value; head.State = lalrState; tokenStack.Push(head); if (!reductionSkipped) { OnReduction((Reduction)tokenStack.Peek()); } return true; }
internal void Add(LRAction action) { actionList.Add(action); }
public bool Parse(TextReader reader) { if (egtDataManager == null) { OnNotLoadedError(); return(false); } TokenQueueStack inputTokens = new TokenQueueStack(); Stack <Token> tokenStack = new Stack <Token>(); tokenStack.Push(new Token()); Stack <Token> groupStack = new Stack <Token>(); LookAheadBuffer lookAheadBuffer = new LookAheadBuffer(reader); ushort lalrState = 0; while (true) { if (inputTokens.Count == 0) { inputTokens.Push(ProduceToken(groupStack, lookAheadBuffer)); OnTokenRead(inputTokens.Peek()); } //Runaway group else if (groupStack.Count != 0) { OnGroupError(); return(false); //Error; abort } else { Token read = inputTokens.Peek(); switch (read.Type) { case SymbolType.Noise: inputTokens.Pop(); break; case SymbolType.Error: OnLexicalError(read.EndPosition, read.Data); return(false); //Error; abort default: LRActionList actionList = egtDataManager.GetLRActionList(lalrState); LRAction parseAction = actionList[read.Symbol]; if (parseAction == null) { HandleSyntaxError(actionList, read); return(false); } switch (parseAction.Type) { case LRActionType.Accept: OnCompleted(tokenStack.Peek().Tag); return(true); case LRActionType.Shift: lalrState = parseAction.Value; read.State = lalrState; tokenStack.Push(read); //It now exists on the Token-Stack and must be eliminated from the queue. inputTokens.Dequeue(); break; case LRActionType.Reduce: if (!DoReduction(tokenStack, lookAheadBuffer, ref lalrState, parseAction)) { return(false); } break; } break; } } } }