/** 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); }
/** 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' } }
/** 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); } }
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); } } }