示例#1
0
        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();
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }