예제 #1
0
        /** For reference to rule r, build
         *
         *  o-e->(r)  o
         *
         *  where (r) is the start of rule r and the trailing o is not linked
         *  to from rule ref state directly (it's done thru the transition(0)
         *  RuleClosureTransition.
         *
         *  If the rule r is just a list of tokens, it's block will be just
         *  a set on an edge o->o->o-set->o->o->o, could inline it rather than doing
         *  the rule reference, but i'm not doing this yet as I'm not sure
         *  it would help much in the NFA->DFA construction.
         *
         *  TODO add to codegen: collapse alt blks that are sets into single matchSet
         */
        public virtual StateCluster BuildRuleRef(Rule refDef, NFAState ruleStart)
        {
            //System.Console.Out.WriteLine( "building ref to rule " + nfa.grammar.name + "." + refDef.name );
            NFAState left = NewState();
            //left.Description = "ref to " + ruleStart.Description;
            NFAState right = NewState();
            //right.Description = "NFAState following ref to " + ruleStart.Description;
            Transition e = new RuleClosureTransition(refDef, ruleStart, right);

            left.AddTransition(e);
            StateCluster g = new StateCluster(left, right);

            return(g);
        }
예제 #2
0
        /** Do a depth-first walk of the state machine graph and
         *  fill a DOT description template.  Keep filling the
         *  states and edges attributes.  We know this is an NFA
         *  for a rule so don't traverse edges to other rules and
         *  don't go past rule end state.
         */
        protected virtual void WalkRuleNFACreatingDOT(StringTemplate dot,
                                                      State s)
        {
            if (markedStates.Contains(s.StateNumber))
            {
                return; // already visited this node
            }

            markedStates.Add(s.StateNumber);   // mark this node as completed.

            // first add this node
            StringTemplate stateST;

            if (s.IsAcceptState)
            {
                stateST = GetTemplates().GetInstanceOf("stopstate");
            }
            else
            {
                stateST = GetTemplates().GetInstanceOf("state");
            }
            stateST.SetAttribute("name", GetStateLabel(s));
            dot.SetAttribute("states", stateST);

            if (s.IsAcceptState)
            {
                return; // don't go past end of rule node to the follow states
            }

            // special case: if decision point, then line up the alt start states
            // unless it's an end of block
            if (((NFAState)s).IsDecisionState)
            {
                GrammarAST n = ((NFAState)s).associatedASTNode;
                if (n != null && n.Type != ANTLRParser.EOB)
                {
                    StringTemplate rankST = GetTemplates().GetInstanceOf("decision-rank");
                    NFAState       alt    = (NFAState)s;
                    while (alt != null)
                    {
                        rankST.SetAttribute("states", GetStateLabel(alt));
                        if (alt.transition[1] != null)
                        {
                            alt = (NFAState)alt.transition[1].Target;
                        }
                        else
                        {
                            alt = null;
                        }
                    }
                    dot.SetAttribute("decisionRanks", rankST);
                }
            }

            // make a DOT edge for each transition
            StringTemplate edgeST = null;

            for (int i = 0; i < s.NumberOfTransitions; i++)
            {
                Transition edge = (Transition)s.GetTransition(i);
                if (edge is RuleClosureTransition)
                {
                    RuleClosureTransition rr = ((RuleClosureTransition)edge);
                    // don't jump to other rules, but display edge to follow node
                    edgeST = GetTemplates().GetInstanceOf("edge");
                    if (rr.Rule.Grammar != grammar)
                    {
                        edgeST.SetAttribute("label", "<" + rr.Rule.Grammar.name + "." + rr.Rule.Name + ">");
                    }
                    else
                    {
                        edgeST.SetAttribute("label", "<" + rr.Rule.Name + ">");
                    }
                    edgeST.SetAttribute("src", GetStateLabel(s));
                    edgeST.SetAttribute("target", GetStateLabel(rr.FollowState));
                    edgeST.SetAttribute("arrowhead", arrowhead);
                    dot.SetAttribute("edges", edgeST);
                    WalkRuleNFACreatingDOT(dot, rr.FollowState);
                    continue;
                }
                if (edge.IsAction)
                {
                    edgeST = GetTemplates().GetInstanceOf("action-edge");
                }
                else if (edge.IsEpsilon)
                {
                    edgeST = GetTemplates().GetInstanceOf("epsilon-edge");
                }
                else
                {
                    edgeST = GetTemplates().GetInstanceOf("edge");
                }
                edgeST.SetAttribute("label", GetEdgeLabel(edge));
                edgeST.SetAttribute("src", GetStateLabel(s));
                edgeST.SetAttribute("target", GetStateLabel(edge.Target));
                edgeST.SetAttribute("arrowhead", arrowhead);
                dot.SetAttribute("edges", edgeST);
                WalkRuleNFACreatingDOT(dot, edge.Target);   // keep walkin'
            }
        }
예제 #3
0
        /** Fill a list of all NFA states visited during the parse */
        protected virtual void ParseEngine(string startRule,
                                           NFAState start,
                                           NFAState stop,
                                           IIntStream input,
                                           Stack <object> ruleInvocationStack,
                                           IDebugEventListener actions,
                                           IList <NFAState> visitedStates)
        {
            NFAState s = start;

            if (actions != null)
            {
                actions.EnterRule(s.nfa.Grammar.FileName, start.enclosingRule.Name);
            }
            int t = input.LA(1);

            while (s != stop)
            {
                if (visitedStates != null)
                {
                    visitedStates.Add(s);
                }
                //Console.Out.WriteLine( "parse state " + s.stateNumber + " input=" + s.nfa.Grammar.getTokenDisplayName( t ) );
                // CASE 1: decision state
                if (s.DecisionNumber > 0 && s.nfa.Grammar.GetNumberOfAltsForDecisionNFA(s) > 1)
                {
                    // decision point, must predict and jump to alt
                    DFA dfa = s.nfa.Grammar.GetLookaheadDFA(s.DecisionNumber);
                    //if ( s.nfa.Grammar.type != GrammarType.Lexer )
                    //{
                    //    Console.Out.WriteLine( "decision: " +
                    //                   dfa.getNFADecisionStartState().Description +
                    //                   " input=" + s.nfa.Grammar.getTokenDisplayName( t ) );
                    //}
                    int m            = input.Mark();
                    int predictedAlt = Predict(dfa);
                    if (predictedAlt == NFA.INVALID_ALT_NUMBER)
                    {
                        string description        = dfa.NFADecisionStartState.Description;
                        NoViableAltException nvae =
                            new NoViableAltException(description,
                                                     dfa.NfaStartStateDecisionNumber,
                                                     s.StateNumber,
                                                     input);
                        if (actions != null)
                        {
                            actions.RecognitionException(nvae);
                        }
                        input.Consume(); // recover
                        throw nvae;
                    }
                    input.Rewind(m);
                    int parseAlt =
                        s.TranslateDisplayAltToWalkAlt(predictedAlt);
                    //if ( s.nfa.Grammar.type != GrammarType.Lexer )
                    //{
                    //    Console.Out.WriteLine( "predicted alt " + predictedAlt + ", parseAlt " + parseAlt );
                    //}
                    NFAState alt;
                    if (parseAlt > s.nfa.Grammar.GetNumberOfAltsForDecisionNFA(s))
                    {
                        // implied branch of loop etc...
                        alt = s.nfa.Grammar.nfa.GetState(s.endOfBlockStateNumber);
                    }
                    else
                    {
                        alt = s.nfa.Grammar.GetNFAStateForAltOfDecision(s, parseAlt);
                    }
                    s = (NFAState)alt.transition[0].Target;
                    continue;
                }

                // CASE 2: finished matching a rule
                if (s.IsAcceptState)
                { // end of rule node
                    if (actions != null)
                    {
                        actions.ExitRule(s.nfa.Grammar.FileName, s.enclosingRule.Name);
                    }
                    if (ruleInvocationStack.Count == 0)
                    {
                        // done parsing.  Hit the start state.
                        //Console.Out.WriteLine( "stack empty in stop state for " + s.enclosingRule );
                        break;
                    }
                    // pop invoking state off the stack to know where to return to
                    NFAState invokingState = (NFAState)ruleInvocationStack.Pop();
                    RuleClosureTransition invokingTransition =
                        (RuleClosureTransition)invokingState.transition[0];
                    // move to node after state that invoked this rule
                    s = invokingTransition.FollowState;
                    continue;
                }

                Transition trans = s.transition[0];
                Label      label = trans.Label;
                if (label.IsSemanticPredicate)
                {
                    FailedPredicateException fpe =
                        new FailedPredicateException(input,
                                                     s.enclosingRule.Name,
                                                     "can't deal with predicates yet");
                    if (actions != null)
                    {
                        actions.RecognitionException(fpe);
                    }
                }

                // CASE 3: epsilon transition
                if (label.IsEpsilon)
                {
                    // CASE 3a: rule invocation state
                    if (trans is RuleClosureTransition)
                    {
                        ruleInvocationStack.Push(s);
                        s = (NFAState)trans.Target;
                        //Console.Out.WriteLine( "call " + s.enclosingRule.name + " from " + s.nfa.Grammar.getFileName() );
                        if (actions != null)
                        {
                            actions.EnterRule(s.nfa.Grammar.FileName, s.enclosingRule.Name);
                        }
                        // could be jumping to new grammar, make sure DFA created
                        if (!s.nfa.Grammar.AllDecisionDFAHaveBeenCreated)
                        {
                            s.nfa.Grammar.CreateLookaheadDFAs();
                        }
                    }
                    // CASE 3b: plain old epsilon transition, just move
                    else
                    {
                        s = (NFAState)trans.Target;
                    }
                }

                // CASE 4: match label on transition
                else if (label.Matches(t))
                {
                    if (actions != null)
                    {
                        if (s.nfa.Grammar.type == GrammarType.Parser ||
                            s.nfa.Grammar.type == GrammarType.Combined)
                        {
                            actions.ConsumeToken(((ITokenStream)input).LT(1));
                        }
                    }
                    s = (NFAState)s.transition[0].Target;
                    input.Consume();
                    t = input.LA(1);
                }

                // CASE 5: error condition; label is inconsistent with input
                else
                {
                    if (label.IsAtom)
                    {
                        MismatchedTokenException mte =
                            new MismatchedTokenException(label.Atom, input);
                        if (actions != null)
                        {
                            actions.RecognitionException(mte);
                        }
                        input.Consume(); // recover
                        throw mte;
                    }
                    else if (label.IsSet)
                    {
                        MismatchedSetException mse =
                            new MismatchedSetException(((IntervalSet)label.Set).ToRuntimeBitSet(),
                                                       input);
                        if (actions != null)
                        {
                            actions.RecognitionException(mse);
                        }
                        input.Consume(); // recover
                        throw mse;
                    }
                    else if (label.IsSemanticPredicate)
                    {
                        FailedPredicateException fpe =
                            new FailedPredicateException(input,
                                                         s.enclosingRule.Name,
                                                         label.SemanticContext.ToString());
                        if (actions != null)
                        {
                            actions.RecognitionException(fpe);
                        }
                        input.Consume(); // recover
                        throw fpe;
                    }
                    else
                    {
                        throw new RecognitionException(input);   // unknown error
                    }
                }
            }
            //Console.Out.WriteLine( "hit stop state for " + stop.enclosingRule );
            if (actions != null)
            {
                actions.ExitRule(s.nfa.Grammar.FileName, stop.enclosingRule.Name);
            }
        }
예제 #4
0
        private void WalkRuleNfaCreatingDgml(State state)
        {
            if (!_markedStates.Add(state.StateNumber))
            {
                return;
            }

            NFAState nfaState = state as NFAState;

            // create the node
            string nodeCategory;

            if (state.IsAcceptState)
            {
                nodeCategory = Categories.StopState;
            }
            else if (nfaState != null && nfaState.IsDecisionState)
            {
                nodeCategory = Categories.DecisionState;
            }
            else
            {
                nodeCategory = Categories.State;
            }

            XElement node = new XElement(Elements.Node,
                                         new XAttribute(Attributes.Id, "state_" + state.StateNumber),
                                         new XAttribute(Attributes.Label, GetStateLabel(state)),
                                         new XAttribute(Attributes.Category, nodeCategory));

            if (nfaState != null && nfaState.IsDecisionState)
            {
                string baseFileName = _grammar.name;
                if (_grammar.implicitLexer)
                {
                    baseFileName += Grammar.grammarTypeToFileNameSuffix[(int)_grammar.type];
                }

                string decisionPath = string.Format("{0}.dec-{1}.dgml", baseFileName, nfaState.DecisionNumber);
                node.Add(new XAttribute(Attributes.Reference, decisionPath));
            }

            _nodes.Add(state, node);
            if (GroupNodes)
            {
                _extraLinks.Add(CreateContainmentLink(_groupId, "state_" + state.StateNumber));
            }

            // don't go past end of rule
            if (state.IsAcceptState)
            {
                return;
            }

            // create links for each transition
            for (int i = 0; i < state.NumberOfTransitions; i++)
            {
                Transition            edge = state.GetTransition(i);
                RuleClosureTransition rr   = edge as RuleClosureTransition;
                if (rr != null)
                {
                    string label;

                    if (rr.Rule.Grammar != _grammar)
                    {
                        label = string.Format("<{0}.{1}>", rr.Rule.Grammar.name, rr.Rule.Name);
                    }
                    else
                    {
                        label = string.Format("<{0}>", rr.Rule.Name);
                    }

                    XElement link = new XElement(Elements.Link,
                                                 new XAttribute(Attributes.Source, "state_" + state.StateNumber),
                                                 new XAttribute(Attributes.Target, "state_" + rr.FollowState),
                                                 new XAttribute(Attributes.Category, Categories.RuleClosureEdge),
                                                 new XAttribute(Attributes.Label, label));

                    _links.Add(new KeyValuePair <State, Transition>(state, edge), link);
                    WalkRuleNfaCreatingDgml(rr.FollowState);
                }
                else
                {
                    string edgeCategory;

                    if (edge.IsAction)
                    {
                        edgeCategory = Categories.ActionEdge;
                    }
                    else if (edge.IsEpsilon)
                    {
                        edgeCategory = Categories.EpsilonEdge;
                    }
                    else if (edge.Label.IsSet || edge.Label.IsAtom)
                    {
                        edgeCategory = Categories.AtomEdge;
                    }
                    else
                    {
                        edgeCategory = Categories.Edge;
                    }

                    XElement link = new XElement(Elements.Link,
                                                 new XAttribute(Attributes.Source, "state_" + state.StateNumber),
                                                 new XAttribute(Attributes.Target, "state_" + edge.Target.StateNumber),
                                                 new XAttribute(Attributes.Category, edgeCategory),
                                                 new XAttribute(Attributes.Label, GetEdgeLabel(edge)));

                    _links.Add(new KeyValuePair <State, Transition>(state, edge), link);
                    WalkRuleNfaCreatingDgml(edge.Target);
                }
            }
        }