private static void GetReachableTransitions(State state, HashSet <Transition> memberSelectTransitions) { foreach (var transition in state.OutgoingTransitions) { if (transition is PopContextTransition) { continue; } if (memberSelectTransitions.Add(transition)) { GetReachableTransitions(transition.TargetState, memberSelectTransitions); } PushContextTransition contextTransition = transition as PushContextTransition; if (contextTransition != null) { foreach (var popTransition in contextTransition.PopTransitions) { if (memberSelectTransitions.Add(popTransition)) { GetReachableTransitions(popTransition.TargetState, memberSelectTransitions); } } } } }
private List <string> AnalyzeInterpreterTrace(InterpretTrace context, RuleBinding memberSelectRule, out Span span) { var transitions = context.Transitions; int expressionLevel = 0; List <string> results = new List <string>(); string identifier = null; span = new Span(); foreach (var transition in transitions) { if (transition.Transition.IsMatch) { switch (transition.Symbol.Value) { case AlloyLexer.IDENTIFIER: case AlloyLexer.KW_THIS: case AlloyLexer.KW_UNIV: case AlloyLexer.KW_IDEN: case AlloyLexer.KW_INT2: case AlloyLexer.KW_SEQINT: case AlloyLexer.INTEGER: if (expressionLevel == 0) { IToken token = transition.Token; identifier = token.Text; span = new Span(token.StartIndex, token.StopIndex - token.StartIndex + 1); } break; case AlloyLexer.DOT: if (expressionLevel == 0) { for (int i = 0; i < results.Count; i++) { results[i] += identifier + "."; identifier = null; } } break; } } else if (transition.Transition.IsContext) { // only need to handle it if we're entering BinOpExpr18 PushContextTransition pushContextTransition = transition.Transition as PushContextTransition; if (pushContextTransition != null && pushContextTransition.TargetState == memberSelectRule.StartState) { expressionLevel++; } PopContextTransition popContextTransition = transition.Transition as PopContextTransition; if (popContextTransition != null && popContextTransition.SourceState == memberSelectRule.EndState) { if (expressionLevel > 0) { expressionLevel--; } } } else if (transition.Transition.IsEpsilon) { if (expressionLevel == 0 && transition.Transition.SourceState == memberSelectRule.StartState) { results.Clear(); results.Add("<context>::"); } } } if (identifier != null) { for (int i = 0; i < results.Count; i++) { results[i] += "[" + identifier + "]"; } } return(results); }
public bool TryStepBackward([NotNull] Transition transition, int symbol, int symbolPosition, out InterpretTrace result) { Requires.NotNull(transition, nameof(transition)); Debug.Assert(Network.States.ContainsKey(transition.SourceState.Id), "Attempted to step outside the network."); Debug.Assert(Network.States.ContainsKey(transition.TargetState.Id), "Attempted to step into the network."); bool boundedStart = BoundedStart; if (!boundedStart && Transitions.Count > 0) { bool ruleBoundary = false; PushContextTransition pushContextTransition = Transitions.First.Value.Transition as PushContextTransition; if (pushContextTransition != null) { /* the rule boundary transfers from outside the rule to inside the rule (or * inside a rule invoked by this rule) */ // first, check if the transition goes to this rule ruleBoundary = Interpreter.BoundaryRules.Contains(Network.StateRules[pushContextTransition.TargetState.Id]); // next, check if the transition starts outside this rule and goes through this rule if (!ruleBoundary) { ruleBoundary = pushContextTransition.ContextIdentifiers .Skip(1) .Any(i => Interpreter.BoundaryRules.Contains(Network.ContextRules[i])); } } if (ruleBoundary) { bool nested = false; for (ContextFrame parent = StartContext.Parent; parent != null; parent = parent.Parent) { Debug.Assert(parent.Context != null); RuleBinding contextRule = Network.ContextRules[parent.Context.Value]; if (Interpreter.BoundaryRules.Contains(contextRule)) { nested = true; } } boundedStart = !nested; } } result = null; if (transition.IsMatch) { if (symbol != NetworkInterpreter.UnknownSymbol && !transition.MatchesSymbol(symbol)) { return(false); } ContextFrame startContext = new ContextFrame(transition.SourceState, this.StartContext.Context, this.StartContext.Parent, Interpreter); result = new InterpretTrace(startContext, this.EndContext, this.Transitions, boundedStart, this.BoundedEnd, boundedStart); if (!boundedStart) { if (!Interpreter.TrackContextTransitions && result.Transitions.Count > 0 && result.Transitions.First.Value.Symbol == null) { result.Transitions.RemoveFirst(); } result.Transitions.AddFirst(new InterpretTraceTransition(transition, symbol, symbolPosition, Interpreter)); } return(true); } PreventContextType preventContextType = PreventContextType.None; if (transition.SourceState.IsOptimized && transition.IsContext) { if (transition is PushContextTransition) { preventContextType = transition.IsRecursive ? PreventContextType.PushRecursive : PreventContextType.Push; } else if (transition is PopContextTransition) { preventContextType = transition.IsRecursive ? PreventContextType.PopRecursive : PreventContextType.Pop; } } if (symbol != NetworkInterpreter.UnknownSymbol && !transition.SourceState.GetSourceSet(preventContextType).Contains(symbol)) { return(false); } if (transition.IsContext) { PopContextTransition popContextTransition = transition as PopContextTransition; if (popContextTransition != null) { ContextFrame subContext = this.StartContext; foreach (var label in popContextTransition.ContextIdentifiers.Reverse()) { subContext = new ContextFrame(popContextTransition.SourceState, null, new ContextFrame(subContext.State, label, subContext.Parent, Interpreter), Interpreter); } result = new InterpretTrace(subContext, this.EndContext, this.Transitions, boundedStart, this.BoundedEnd, boundedStart); if (!boundedStart) { if (!Interpreter.TrackContextTransitions && result.Transitions.Count > 0 && result.Transitions.First.Value.Symbol == null) { result.Transitions.RemoveFirst(); } result.Transitions.AddFirst(new InterpretTraceTransition(transition, Interpreter)); } return(true); } PushContextTransition pushContextTransition = transition as PushContextTransition; if (pushContextTransition != null) { ContextFrame startContext = this.StartContext; ContextFrame endContext = this.EndContext; for (int i = pushContextTransition.ContextIdentifiers.Count - 1; i >= 0; i--) { int label = pushContextTransition.ContextIdentifiers[i]; if (startContext.Parent != null) { Debug.Assert(startContext.Parent.Context.HasValue); // if the start context has a state stack, pop an item off it if (startContext.Parent.Context != label) { return(false); } startContext = new ContextFrame(transition.SourceState, null, startContext.Parent.Parent, Interpreter); } else { int?headContext = endContext.HeadContext; if (headContext != null) { if (!Network.Optimizer.CanNestContexts(label, headContext.Value)) { return(false); } } else { if (!Network.Optimizer.IsStateInContext(label, endContext.State.Id)) { return(false); } } ContextFrame headContextFrame = null; for (int j = 0; j <= i; j++) { headContextFrame = new ContextFrame(null, pushContextTransition.ContextIdentifiers[j], headContextFrame, Interpreter); } // else we add a "predicate" to the end context endContext = endContext.AddHeadContext(headContextFrame); if (!object.ReferenceEquals(startContext.State, transition.SourceState)) { startContext = new ContextFrame(transition.SourceState, startContext.Context, startContext.Parent, Interpreter); } break; } } result = new InterpretTrace(startContext, endContext, this.Transitions, boundedStart, this.BoundedEnd, boundedStart); if (!boundedStart) { if (!Interpreter.TrackContextTransitions && result.Transitions.Count > 0 && result.Transitions.First.Value.Symbol == null) { result.Transitions.RemoveFirst(); } result.Transitions.AddFirst(new InterpretTraceTransition(transition, Interpreter)); } return(true); } throw new NotSupportedException("Unknown context transition."); } else if (transition.IsEpsilon) { ContextFrame startContext = new ContextFrame(transition.SourceState, this.StartContext.Context, this.StartContext.Parent, Interpreter); result = new InterpretTrace(startContext, this.EndContext, this.Transitions, boundedStart, this.BoundedEnd, true); return(true); } throw new NotSupportedException("Unknown transition type."); }