Ejemplo n.º 1
0
        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.");
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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);
                    }
                }
            }
        }