public void TestEncodeAndDecode( [Values( ParserActionKind.Fail, ParserActionKind.Accept, ParserActionKind.Reduce, ParserActionKind.Shift )] ParserActionKind kind, [Values(0, 1, 1024, ushort.MaxValue)] int value1) { int cell = ParserAction.Encode(kind, value1); var action = ParserAction.Decode(cell); if (kind == ParserActionKind.Fail) { Assert.AreEqual(kind, action.Kind); } else { Assert.IsNotNull(action); Assert.AreEqual(kind, action.Kind); Assert.AreEqual(value1, action.Value1); } Assert.AreEqual(kind, ParserAction.GetKind(cell)); Assert.AreEqual(value1, ParserAction.GetId(cell)); }
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); } }
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 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 bool TryResolveShiftReduce(int actionX, int actionY, int incomingToken, out int output) { output = 0; int shiftAction, reduceAction; if (ParserAction.GetKind(actionX) == ParserActionKind.Shift && ParserAction.GetKind(actionY) == ParserActionKind.Reduce) { shiftAction = actionX; reduceAction = actionY; } else if (ParserAction.GetKind(actionY) == ParserActionKind.Shift && ParserAction.GetKind(actionX) == ParserActionKind.Reduce) { shiftAction = actionY; reduceAction = actionX; } else { #if LALR1_TOLERANT // Unsupported conflict type. Use first action output = actionX; #else output = ParserAction.Encode(ParserActionKind.Conflict, 0); #endif return(false); } var shiftTokenPrecedence = grammar.GetTermPrecedence(incomingToken); var reduceRulePrecedence = grammar.GetProductionPrecedence(ParserAction.GetId(reduceAction)); if (shiftTokenPrecedence == null && reduceRulePrecedence == null) { #if LALR1_TOLERANT // In case of conflict prefer shift over reduce output = shiftAction; #else output = ParserAction.Encode(ParserActionKind.Conflict, 0); #endif return(false); } else if (shiftTokenPrecedence == null) { output = reduceAction; } else if (reduceRulePrecedence == null) { output = shiftAction; } else if (Precedence.IsReduce(reduceRulePrecedence, shiftTokenPrecedence)) { output = reduceAction; } else { output = shiftAction; } return(true); }