void PopStack(SyntaxContext currentContext, SyntaxMatch curMatch)
            {
                if (ContextStack.Count() == 1)
                {
                    MatchStack = MatchStack.Clear();
                    ScopeStack = new ScopeStack(highlighting.definition.Scope);
                    return;
                }
                ContextStack = ContextStack.Pop();
                if (!MatchStack.IsEmpty)
                {
                    PopScopeStack(MatchStack.Peek()?.Scope);
                    MatchStack = MatchStack.Pop();
                }
                PopScopeStack(currentContext.MetaScope);

                if (curMatch.Scope.Count > 0 && !ScopeStack.IsEmpty)
                {
                    for (int i = 0; i < curMatch.Scope.Count; i++)
                    {
                        ScopeStack = ScopeStack.Pop();
                    }
                }
            }
Exemple #2
0
    public static MatchResult Match(string rootProdName, TokenQueue q, out Ast.SqliteSyntaxProduction ast)
    {
        // we use an explicit stack rather than function call recursion because our BNF grammar is deeply nested,
        // particularly the productions for 'expr'.
        var stack = new MatchStack {
            Queue = q
        };

        stack.Push(SqliteGrammar.Prods[rootProdName]);
        MatchResult?rootResult = null;

        Ast.SqliteSyntaxProduction rootAst = null;

        Action <MatchResult, Ast.SqliteSyntaxProduction> finishFrame = (frameResult, frameAstProd) => {
            stack.Pop();
            var parentFrame = stack.Peek();
            if (parentFrame == null)
            {
                rootResult = frameResult;
                rootAst    = frameAstProd;
            }
            else
            {
                parentFrame.SubResult = frameResult;
                if (frameResult.IsMatch)
                {
                    parentFrame.AstProd.Items.Add(frameAstProd);
                }
            }
        };

#if MATCHER_LOG
        var matcherLogWriter        = File.CreateText(@"C:\temp\matcher.log");
        int matcherLogPreviousDepth = 0;
#endif

        // trampoline loop
        while (!rootResult.HasValue && stack.Any())
        {
#if MATCHER_LOG
            stack.DebugDump(matcherLogWriter, q.GetLocation(), q.Substring(q.GetLocation(), 1),
                            matcherLogPreviousDepth > stack.Count);
            matcherLogPreviousDepth = stack.Count;
#endif

            var frame  = stack.Peek();
            var result = frame.Prod.Terms[frame.TermIndex].MatchStep(stack, frame, q);
            if (result.HasValue)
            {
                // we are done matching this term
                if (result.Value.IsMatch)
                {
                    // move to the next term in the production.
                    frame.Clear(all: false);
                    frame.TermIndex++;
                    if (frame.TermIndex >= frame.Prod.Terms.Length)
                    {
                        // we have matched this full production
                        var prodEndLoc = q.GetLocation();
                        frame.AstProd.StartToken = frame.ProdStartLoc;
                        frame.AstProd.NumTokens  = prodEndLoc - frame.ProdStartLoc;
                        frame.AstProd.Text       = q.Substring(frame.ProdStartLoc, prodEndLoc - frame.ProdStartLoc);
                        finishFrame(MatchResult.Matched, frame.AstProd);
                    }
                }
                else
                {
                    // we needed a match and didn't find one.  we have to abandon this production.
                    finishFrame(result.Value, null);
                }
            }
        }

#if MATCHER_LOG
        matcherLogWriter.Close();
#endif

        if (!rootResult.HasValue && !stack.Any())   // detect bugs
        {
            throw new Exception("Expected a MatchResult but one was not set.");
        }

        ast = rootAst;
        return(rootResult.Value);
    }
 private object CurrentStackId()
 {
     return(MatchStack.Count == 0 ? null : MatchStack.Peek());
 }