private void AssignAction(int state, int token, ParserAction action) { int cell = ParserAction.Encode(action); int currentCell = actionTable.Get(state, token); if (currentCell == 0) { actionTable.Set(state, token, cell); } else if (currentCell != cell) { int resolvedCell; if (!TryResolveShiftReduce(currentCell, cell, token, out resolvedCell)) { RequiresGlr = true; ParserConflictInfo conflict; var key = new TransitionKey(state, token); if (!transitionToConflict.TryGetValue(key, out conflict)) { conflict = new ParserConflictInfo(state, token); transitionToConflict[key] = conflict; conflict.AddAction(currentCell); } if (!conflict.Actions.Contains(action)) { conflict.AddAction(action); } } actionTable.Set(state, token, resolvedCell); } }
public static int Encode(ParserAction action) { int result = ((byte)action.Kind) | (action.Value1 << Value1StartBit) | (action.Size << Value2StartBit) ; return result; }
public static ParserActionKind Decode(int cell, ref ParserAction result) { ParserActionKind kind = (ParserActionKind)(cell & KindMask); result.Kind = kind; if (kind != ParserActionKind.Fail) { result.Value1 = (cell & Value1Mask) >> Value1StartBit; result.Size = (short)((cell & Value2Mask) >> Value2StartBit); } return kind; }
public static ParserActionKind Decode(int cell, ref ParserAction result) { ParserActionKind kind = (ParserActionKind)(cell & KindMask); result.Kind = kind; if (kind != ParserActionKind.Fail) { result.Value1 = (cell & Value1Mask) >> Value1StartBit; result.Size = (short)((cell & Value2Mask) >> Value2StartBit); } return(kind); }
private ParserAction LookaheadAction(int token) { var act = ParserAction.Decode(actionTable(stateStack.PeekTag(), token)); TNode value; while (act.Kind == ParserActionKind.Reduce) { this.currentRule = grammar.Productions[act.ProductionId]; stateStack.Start = stateStack.Count - currentRule.PatternTokens.Length; value = producer.CreateBranch( currentRule, stateStack.PeekTail(currentRule.PatternTokens.Length), (IStackLookback <TNode>)stateStack); stateStack.Pop(currentRule.PatternTokens.Length); act = ParserAction.Decode(actionTable(stateStack.PeekTag(), currentRule.OutcomeToken)); while (act.Kind == ParserActionKind.ShiftReduce) // == GotoReduce { stateStack.Push(-1, value); this.currentRule = grammar.Productions[act.ProductionId]; stateStack.Start = stateStack.Count - currentRule.PatternTokens.Length; value = producer.CreateBranch( currentRule, stateStack.PeekTail(currentRule.PatternTokens.Length), (IStackLookback <TNode>)stateStack); stateStack.Pop(currentRule.PatternTokens.Length); act = ParserAction.Decode(actionTable(stateStack.PeekTag(), currentRule.OutcomeToken)); } stateStack.Push(act.State, value); // reduce or final shift act = ParserAction.Decode(actionTable(act.State, token)); } return(act); }
private void GetReductions(State state, int token) { pendingReductionsCount = 0; ParserAction action = GetDfaCell(state, token); Production rule; switch (action.Kind) { case ParserActionKind.Reduce: rule = grammar.Productions[action.ProductionId]; pendingReductionsCount = 1; pendingReductions[0] = new ModifiedReduction(rule, action.Size); break; case ParserActionKind.Accept: accepted = true; break; case ParserActionKind.Conflict: int start = action.Value1; int last = action.Value1 + action.Value2; while (start != last) { var conflictAction = ParserAction.Decode(conflictActionsTable[start++]); switch (conflictAction.Kind) { case ParserActionKind.Reduce: var crule = grammar.Productions[conflictAction.ProductionId]; pendingReductions[pendingReductionsCount++] = new ModifiedReduction(crule, conflictAction.Size); break; } } break; } }
private StreamWriter DescribeAction( IReportData data, ParserAction action, StreamWriter output, string indent) { switch (action.Kind) { case ParserActionKind.Shift: output.Write(indent); output.Write("Shift to the state I"); output.Write(action.State + ""); output.WriteLine(":"); DescribeState(data, action.State, output, indent + indent); break; case ParserActionKind.ShiftReduce: output.Write(indent); output.WriteLine("Shift-Reduce on the rule:"); output.Write(indent + indent); DescribeRule(data, action.ProductionId, output); output.WriteLine(); break; case ParserActionKind.Reduce: output.Write(indent); output.WriteLine("Reduce on the rule:"); output.Write(indent + indent); DescribeRule(data, action.ProductionId, output); output.WriteLine(); break; case ParserActionKind.Accept: output.Write(indent); output.WriteLine("Accept."); break; } return output; }
private void Reducer(int lookahead = -1) { while (!R.IsEmpty) { GssReducePath <T> path = R.Dequeue(); int X = path.Rule.OutcomeToken; int m = path.Size; GssNode <T> u = path.LeftNode; State k = u.State; T z; if (m == 0) { z = producer.GetDefault(X, (IStackLookback <T>)u); } else { path.CopyDataTo(nodeBuffer); T Λ = producer.CreateBranch( path.Rule, new ArraySlice <T>(nodeBuffer, 0, path.Size), lookback: path.LeftNode); int c = u.Layer; T currentValue; var Nkey = GetNKey(X, c); if (N.TryGetValue(Nkey, out currentValue)) { z = producer.Merge(currentValue, Λ, (IStackLookback <T>)u); } else { z = Λ; } N[Nkey] = z; } State l; var action = ParserAction.Decode(transition(k, X)); switch (action.Kind) { case ParserActionKind.Shift: l = action.State; break; case ParserActionKind.ShiftReduce: // Goto-Reduce action PlanShiftReduce( u, X, z, action.ProductionId, action.Size); continue; default: throw new InvalidOperationException( "Internal error: Non-term action should be shift or shift-reduce, but got " + Enum.GetName(typeof(ParserActionKind), action.Kind)); } bool stateAlreadyExists = gss.GetFrontNode(l, lookahead) != null; // Goto on non-term produced by rule. var newLink = gss.Push(u, l, z, lookahead); if (lookahead < 0) { continue; } if (stateAlreadyExists) { if (newLink != null && m != 0) { GetReductions(l, lookahead); for (int i = 0; i != pendingReductionsCount; ++i) { var red = pendingReductions[i]; if (red.Size != 0) { R.Enqueue(newLink, red.Rule, red.Size); } } } } else { var w = gss.GetFrontNode(l, lookahead); GetReductions(l, lookahead); //foreach (var red in reductions) for (int i = 0; i != pendingReductionsCount; ++i) { var red = pendingReductions[i]; if (red.Size == 0) { R.Enqueue(w, red.Rule, 0); } } if (m != 0) { for (int i = 0; i != pendingReductionsCount; ++i) { var red = pendingReductions[i]; if (red.Size != 0) { R.Enqueue(newLink, red.Rule, red.Size); } } } } } }
private void FillDfaTable(DotState[] states) { for (int i = 0; i != states.Length; ++i) { var state = states[i]; Debug.Assert(i == state.Index); foreach (var item in state.Items) { if (!item.IsReduce) { int nextToken = item.NextToken; if (canOptimizeReduceStates && item.IsShiftReduce && !state.Transitions.Exists(t => t.Tokens.Contains(nextToken))) { var action = new ParserAction { Kind = ParserActionKind.ShiftReduce, ProductionId = item.ProductionId }; AssignAction(i, nextToken, action); } else { var action = new ParserAction { Kind = ParserActionKind.Shift, State = state.GetNextIndex(nextToken) }; AssignAction(i, nextToken, action); } } else if (item.IsAugmented) { var action = new ParserAction { Kind = ParserActionKind.Accept }; AssignAction(i, PredefinedTokens.Eoi, action); } else { var action = new ParserAction { Kind = ParserActionKind.Reduce, ProductionId = item.ProductionId }; foreach (var lookahead in item.LA) { AssignAction(i, lookahead, action); } } } } }
private void BuildConflictTable() { var conflictList = new List<int>(); foreach (var conflict in transitionToConflict.Values) { var refAction = new ParserAction { Kind = ParserActionKind.Conflict, Value1 = conflictList.Count, Size = (short)conflict.Actions.Count }; actionTable.Set(conflict.State, conflict.Token, ParserAction.Encode(refAction)); foreach (var action in conflict.Actions) { conflictList.Add(ParserAction.Encode(action)); } } this.conflictActionTable = conflictList.ToArray(); }
private static ParserAction GetShift(LanguageData data, ParserAction x) { switch (x.Kind) { case ParserActionKind.Shift: case ParserActionKind.ShiftReduce: return x; case ParserActionKind.Conflict: int start = x.Value1; int count = x.Value2; int last = start + count; for (; start != last; ++start) { var cAction = ParserAction.Decode(data.ParserConflictActionTable[start]); switch (cAction.Kind) { case ParserActionKind.Shift: case ParserActionKind.ShiftReduce: return cAction; } } break; } return ParserAction.FailAction; }
private static bool HaveSameShifts(LanguageData data, ParserAction x, ParserAction y) { var xShift = GetShift(data, x); var yShift = GetShift(data, y); return xShift == yShift; }
private static bool HaveComptibleReductions(LanguageData data, ParserAction pAction, ParserAction qAction) { return ( pAction.Kind != ParserActionKind.Reduce && qAction.Kind != ParserActionKind.Reduce) || ( pAction.Kind == ParserActionKind.Reduce && qAction.Kind == ParserActionKind.Reduce && pAction.ProductionId == qAction.ProductionId ); }
private bool IsAccepting(State s) { int cell = transition(s, PredefinedTokens.Eoi); return(ParserAction.GetKind(cell) == ParserActionKind.Accept); }
private void PrintAction(IReportData data, SymbolBase symbol, StreamWriter output, ParserAction action) { if (action == null || action.Kind == ParserActionKind.Fail) { return; } output.Write(Indent); output.Write(symbol.Name); output.Write(" "); switch (action.Kind) { case ParserActionKind.Shift: output.Write("shift and go to state "); output.Write(action.State); break; case ParserActionKind.Reduce: output.Write("reduce using rule "); output.Write(action.ProductionId); break; case ParserActionKind.ShiftReduce: output.Write("shift-reduce using rule "); output.Write(action.ProductionId); break; case ParserActionKind.Accept: output.WriteLine("accept"); break; } output.WriteLine(); }
public static ParserAction Decode(int cell) { ParserAction result = new ParserAction(); Decode(cell, ref result); return result; }
public IReceiver <Msg> Next(Msg envelope) { stateStack.BeginEdit(); int id = envelope.Id; MsgData data = envelope.FirstData; START: ParserAction action = LookaheadAction(id); switch (action.Kind) { case ParserActionKind.Fail: if (isVerifier) { return(null); } // ReportUnexpectedToken(msg, stateStack.PeekTag()); return(RecoverFromError(envelope)); case ParserActionKind.Resolve: id = action.RolvedToken; while (true) { if (data.Token == id) { // Successfully resolved to a particular token goto START; } data = data.Next; if (data == null) { // Desired token was not present in Msg goto case ParserActionKind.Fail; } } case ParserActionKind.Fork: case ParserActionKind.Conflict: logging.Write( new LogEntry { Severity = Severity.Error, Location = envelope.Location, HLocation = envelope.HLocation, Message = "Hit parser conflict on token " + grammar.SymbolName(envelope.Id) }); return(null); case ParserActionKind.Shift: { stateStack.Push(action.State, producer.CreateLeaf(envelope, data)); break; } case ParserActionKind.ShiftReduce: { TNode value = producer.CreateLeaf(envelope, data); do { stateStack.Push(-1, value); this.currentRule = grammar.Productions[action.ProductionId]; stateStack.Start = stateStack.Count - currentRule.PatternTokens.Length; value = producer.CreateBranch( currentRule, stateStack.PeekTail(currentRule.PatternTokens.Length), (IStackLookback <TNode>)stateStack); stateStack.Pop(currentRule.PatternTokens.Length); action = ParserAction.Decode(actionTable(stateStack.PeekTag(), currentRule.OutcomeToken)); }while (action.Kind == ParserActionKind.ShiftReduce); if (action.Kind == ParserActionKind.Fail) { return(null); } Debug.Assert(action.Kind == ParserActionKind.Shift); stateStack.Push(action.State, value); break; } case ParserActionKind.Accept: producer.Result = stateStack.Peek(); return(FinalReceiver <Msg> .Instance); default: throw new InvalidOperationException("Internal error: Unsupported parser action"); } stateStack.EndEdit(); this.priorInput = envelope; return(this); }
internal void AddAction(ParserAction action) { actions.Add(action); }
private ParserAction GetDfaCell(State state, int token) { return(ParserAction.Decode(transition(state, token))); }
private bool FillAmbiguousTokenActions(DotState[] states, bool isGlr) { for (int i = 0; i != states.Length; ++i) { var state = states[i]; foreach (var ambToken in grammar.AmbiguousSymbols) { var validTokenActions = new Dictionary<int,int>(); foreach (int token in ambToken.Tokens) { int cell = data.Get(i, token); if (cell == 0) { continue; } validTokenActions.Add(token, cell); } switch (validTokenActions.Count) { case 0: // AmbToken is entirely non-acceptable for this state data.Set(i, ambToken.Index, 0); break; case 1: { var pair = validTokenActions.First(); if (pair.Key == ambToken.MainToken) { // ambToken action is the same as for the main token data.Set(i, ambToken.Index, pair.Value); } else { // Resolve ambToken to a one of the underlying tokens. // In runtime transition will be acceptable when this token // is in Msg and non-acceptable when this particular token // is not in Msg. var action = new ParserAction { Kind = ParserActionKind.Resolve, Value1 = pair.Key }; data.Set(i, ambToken.Index, ParserAction.Encode(action)); } } break; default: if (validTokenActions.Values.Distinct().Count() == 1) { // Multiple tokens but with the same action goto case 1; } if (!isGlr) { return false; } // This kind of ambiguity requires GLR to follow all alternate tokens { var pair = validTokenActions.First(); var forkAction = new ParserAction { Kind = ParserActionKind.Fork, Value1 = pair.Key }; data.Set(i, ambToken.Index, ParserAction.Encode(forkAction)); } break; } } } return true; }
private void FillDfaTable(DotState[] states) { for (int i = 0; i != states.Length; ++i) { var state = states[i]; foreach (var item in state.Items) { if (!item.IsReduce) { int nextToken = item.NextToken; if (canOptimizeReduceStates && item.IsShiftReduce && !state.Transitions.Exists(t => t.Tokens.Contains(nextToken))) { var action = new ParserAction { Kind = ParserActionKind.ShiftReduce, ProductionId = item.ProductionId, Size = (short)item.Size }; AddAction(i, nextToken, action); } else { var action = new ParserAction { Kind = ParserActionKind.Shift, State = state.GetNextIndex(nextToken) }; AddAction(i, nextToken, action); } } bool isStartRule = item.IsAugmented; if (item.IsReduce || grammar.IsTailNullable(item)) { ParserAction action; if (isStartRule) { if (item.Position == 0) { continue; } else { action = new ParserAction { Kind = ParserActionKind.Accept }; } } else { action = new ParserAction { Kind = ParserActionKind.Reduce, ProductionId = item.ProductionId, Size = (short)item.Position }; } foreach (var lookahead in item.LA) { if (!IsValueOnlyEpsilonReduceItem(item, state, lookahead)) { AddAction(i, lookahead, action); } } } } } }