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."); }
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); }
private void StepForward(ICollection <InterpretTrace> result, ICollection <int> states, InterpretTrace context, int symbol, int symbolPosition, PreventContextType preventContextType) { foreach (var transition in context.EndContext.State.OutgoingTransitions) { if (transition.IsContext) { PopContextTransition popContextTransition = transition as PopContextTransition; if (popContextTransition != null && context.EndContext.Parent != null) { if (popContextTransition.ContextIdentifiers[0] != context.EndContext.Parent.Context) { continue; } } switch (preventContextType) { case PreventContextType.Pop: if (!transition.IsRecursive && (transition is PopContextTransition)) { continue; } break; case PreventContextType.PopRecursive: if (transition.IsRecursive && (transition is PopContextTransition)) { continue; } break; case PreventContextType.Push: if (!transition.IsRecursive && (transition is PushContextTransition)) { continue; } break; case PreventContextType.PushRecursive: if (transition.IsRecursive && (transition is PushContextTransition)) { continue; } break; default: break; } } InterpretTrace step; if (context.TryStepForward(transition, symbol, symbolPosition, out step)) { if (transition.IsMatch) { result.Add(step); continue; } bool recursive = transition.TargetState.IsForwardRecursive; bool addRecursive = false; if (recursive) { addRecursive = !states.Contains(transition.TargetState.Id); if (!addRecursive && (!(transition is PopContextTransition) || context.EndContext.Parent == null)) { continue; } } if (addRecursive) { states.Add(transition.TargetState.Id); } PreventContextType nextPreventContextType = PreventContextType.None; if (context.EndContext.State.IsOptimized) { if (transition is PushContextTransition) { nextPreventContextType = transition.IsRecursive ? PreventContextType.PushRecursive : PreventContextType.Push; } else if (transition is PopContextTransition) { nextPreventContextType = transition.IsRecursive ? PreventContextType.PopRecursive : PreventContextType.Pop; } } StepForward(result, states, step, symbol, symbolPosition, nextPreventContextType); if (addRecursive) { states.Remove(transition.TargetState.Id); } } } }