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;
        }
Beispiel #4
0
        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);
        }
Beispiel #6
0
        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;
        }
Beispiel #8
0
        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();
        }
Beispiel #11
0
        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;
        }
Beispiel #12
0
 private static bool HaveSameShifts(LanguageData data, ParserAction x, ParserAction y)
 {
     var xShift = GetShift(data, x);
     var yShift = GetShift(data, y);
     return xShift == yShift;
 }
Beispiel #13
0
 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
         );
 }
Beispiel #14
0
        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);
 }
Beispiel #19
0
 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);
                            }
                        }
                    }
                }
            }
        }