Example #1
0
 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;
 }
Example #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);
        }