コード例 #1
0
    public static Result ReadStmt(TokenQueue q, out Ast.SqliteSyntaxProduction ast, string rootProdName = "sql-stmt")
    {
        var startingLocation = q.GetLocation();
        var matchResult      = Matcher.Match(rootProdName, q, out ast);
        var numTokens        = q.GetLocation() - startingLocation;

        if (matchResult.IsMatch)
        {
            return(new Result(numTokens));
        }
        else
        {
            return(new Result(matchResult.ErrorMessage ?? "Not a statement.", numTokens));
        }
    }
コード例 #2
0
    public static Result ReadExpr(TokenQueue q, out Ast.SqliteSyntaxProduction ast)
    {
        var startingLocation = q.GetLocation();
        var matchResult      = Matcher.Match("expr", q, out ast);
        var numTokens        = q.GetLocation() - startingLocation;

        if (matchResult.IsMatch)
        {
            return(new Result(numTokens));
        }
        else
        {
            return(new Result(matchResult.ErrorMessage ?? "Not an expression.", numTokens));
        }
    }
コード例 #3
0
ファイル: Matcher.cs プロジェクト: electroly/sqlnotebook
 public void Clear(bool all = true)
 {
     if (all)
     {
         ProdStartLoc = 0;
         Prod         = null;
         TermIndex    = 0;
         AstProd      = null;
     }
     OptionalState          = OptionalTermState.Start;
     OptionalStartLoc       = 0;
     OrState                = OrTermState.Start;
     OrProdIndex            = 0;
     OrStartLoc             = 0;
     ProdMatched            = false;
     ListState              = ListTermState.Start;
     ListCount              = 0;
     ListSeparatorStartLoc  = 0;
     SubResult.ErrorMessage = "Uninitialized result";
     SubResult.IsMatch      = false;
 }
コード例 #4
0
ファイル: Matcher.cs プロジェクト: electroly/sqlnotebook
    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);
    }