Exemple #1
0
    public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
    {
        int idx   = (int)q.Take().Type;
        var match = idx >= 0 && idx < _bitmap.Length && _bitmap[idx];

        return(match ? MatchResult.Matched : MatchResult.NoMatch);
    }
            void PushStack(SyntaxMatch curMatch, IEnumerable <SyntaxContext> nextContexts)
            {
                if (nextContexts != null)
                {
                    bool first = true;
                    foreach (var nextContext in nextContexts)
                    {
                        var ctx = nextContext;
                        if (curMatch.WithPrototype != null)
                        {
                            ctx = new SyntaxContextWithPrototype(nextContext, curMatch.WithPrototype);
                        }

                        if (first)
                        {
                            MatchStack = MatchStack.Push(curMatch);
                            first      = false;
                        }
                        else
                        {
                            MatchStack = MatchStack.Push(null);
                        }
                        ContextStack = ContextStack.Push(ctx);
                        PushScopeStack(ctx.MetaScope);
                        PushScopeStack(ctx.MetaContentScope);
                    }
                }
            }
        private void MatchPush()
        {
            var objId = new object();

            MatchStack.Push(objId);
            LastMatch.StackPosition = MatchStack.Count;
            LastMatch.StackId       = objId;
        }
Exemple #4
0
        public static Dictionary ToDictionary(string strText)
        {
            strText = strText.Trim();
            Debug.Assert(!string.IsNullOrEmpty(strText));
            if (strText[0] != '{' || strText[strText.Length - 1] != '}')
            {
                return(null);
            }

            Dictionary dict = new Dictionary();

            strText = strText.Substring(1, strText.Length - 2); // remove '{' & '}'
            int begin = 0;
            int end   = strText.Length;

            while (begin < end)
            {
                int        beginKey = begin;
                int        endKey   = beginKey;
                MatchStack stackKey = new MatchStack();
                while (endKey < end && (!stackKey.IsEmpty() || strText[endKey] != ':'))
                {
                    stackKey.Push(strText[endKey]);
                    endKey++;
                }
                Debug.Assert(endKey < end);
                string key = strText.Substring(beginKey, endKey - beginKey).Trim();
                Debug.Assert(key.Length < 2 || (key[0] == '"') == (key[key.Length - 1] == '"'));
                if (key.Length >= 2 && key[0] == '"' && key[key.Length - 1] == '"')
                {
                    key = key.Substring(1, key.Length - 2);
                }

                int        beginValue = endKey + 1;
                int        endValue   = beginValue;
                MatchStack stackValue = new MatchStack();
                while (endValue < end && (!stackValue.IsEmpty() || strText[endValue] != ','))
                {
                    stackValue.Push(strText[endValue]);
                    endValue++;
                }
                string value = strText.Substring(beginValue, endValue - beginValue).Trim();
                Debug.Assert(value.Length < 2 || (value[0] == '"') == (value[value.Length - 1] == '"'));
                if (value.Length >= 2 && value[0] == '"' && value[value.Length - 1] == '"')
                {
                    value = value.Substring(1, value.Length - 2);
                }

                begin = endValue + 1;

                Debug.Assert(!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value));
                dict.Add(key, value);
            }

            return(dict);
        }
        private void MatchPop()
        {
            if (MatchStack.Count == 0)
            {
                LastMatch.StackPosition = -1;
                LastMatch.StackId       = null;
                return;
            }

            LastMatch.StackPosition = MatchStack.Count;
            LastMatch.StackId       = MatchStack.Pop();
        }
Exemple #6
0
    public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
    {
        switch (q.Take().Type)
        {
        case TokenType.Id:
        case TokenType.Ties:
        case TokenType.Variable when AllowVariable:
            return(MatchResult.Matched);

        default:
            return(MatchResult.NoMatch);
        }
    }
Exemple #7
0
 public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
 {
     if (!frame.ProdMatched)
     {
         if (_prod == null)
         {
             _prod = SqliteGrammar.Prods[ProdName];
         }
         stack.Push(_prod);
         frame.ProdMatched = true;
         return(null);
     }
     else
     {
         return(frame.SubResult);
     }
 }
Exemple #8
0
 public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
 {
     if (frame.OrState == OrTermState.Start)
     {
         // try to match the first sub-production
         stack.Push(Prods[0]);
         frame.OrState     = OrTermState.Match;
         frame.OrProdIndex = 0;
         frame.OrStartLoc  = q.GetLocation();
         return(null);
     }
     else if (frame.OrState == OrTermState.Match)
     {
         // we have finished matching one of the productions.  if it matched, then we're done.  if not, move on
         // to the next production.
         var result = frame.SubResult;
         if (result.IsMatch)
         {
             return(MatchResult.Matched);
         }
         else if (result.ErrorMessage == null)
         {
             // no match.  rewind to the beginning and retry with the next one.
             q.Jump(frame.OrStartLoc);
             frame.OrProdIndex++;
             if (frame.OrProdIndex >= Prods.Length)
             {
                 // we have exhausted all of the possibilities and none of them matched.
                 return(MatchResult.NoMatch);
             }
             stack.Push(Prods[frame.OrProdIndex]);
             return(null);
         }
         else
         {
             // started to match but mismatched past the point of no return.
             return(result);
         }
     }
     else
     {
         throw new Exception($"Unrecognized state: {frame.OrState}");
     }
 }
Exemple #9
0
        public static Array ToArray(string strText)
        {
            strText = strText.Trim();
            Debug.Assert(!string.IsNullOrEmpty(strText));
            if (strText[0] != '[' || strText[strText.Length - 1] != ']')
            {
                return(null);
            }

            Array array = new Array();

            strText = strText.Substring(1, strText.Length - 2); // remove '[' & ']'
            int begin = 0;
            int end   = strText.Length;

            while (begin < end)
            {
                int        beginItem = begin;
                int        endItem   = beginItem;
                MatchStack stackKey  = new MatchStack();
                while (endItem < end && (!stackKey.IsEmpty() || strText[endItem] != ','))
                {
                    stackKey.Push(strText[endItem]);
                    endItem++;
                }
                string item = strText.Substring(beginItem, endItem - beginItem).Trim();
                Debug.Assert(item.Length < 2 || (item[0] == '"') == (item[item.Length - 1] == '"'));
                if (item.Length >= 2 && item[0] == '"' && item[item.Length - 1] == '"')
                {
                    item = item.Substring(1, item.Length - 2);
                }

                begin = endItem + 1;

                Debug.Assert(!string.IsNullOrEmpty(item));
                array.Add(item);
            }

            return(array);
        }
Exemple #10
0
 public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
 {
     if (frame.OptionalState == OptionalTermState.Start)
     {
         // try to match the sub-production
         stack.Push(Prod);
         frame.OptionalState    = OptionalTermState.Match;
         frame.OptionalStartLoc = q.GetLocation();
         return(null);
     }
     else if (frame.OptionalState == OptionalTermState.Match)
     {
         // done matching the sub-production
         var result = frame.SubResult;
         if (result.IsMatch)
         {
             // the optional term is indeed present.
             return(MatchResult.Matched);
         }
         else if (result.ErrorMessage == null)
         {
             // it didn't match but wasn't an error.  this is fine, but we do have to walk the cursor back to
             // where it started since we effectively "matched" zero tokens.
             q.Jump(frame.OptionalStartLoc);
             return(MatchResult.Matched);
         }
         else
         {
             // it started to match but then mismatched past the point of no return.  that's an error.
             return(result);
         }
     }
     else
     {
         throw new Exception($"Unrecognized state: {frame.OptionalState}");
     }
 }
            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 #12
0
 public abstract MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q);
 private object CurrentStackId()
 {
     return(MatchStack.Count == 0 ? null : MatchStack.Peek());
 }
Exemple #14
0
 public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
 {
     return(q.Take().Text.ToLower() == Text.ToLower() ? MatchResult.Matched : MatchResult.NoMatch);
 }
Exemple #15
0
 public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
 {
     return(q.Take().Type == TokenType.String ? MatchResult.Matched : MatchResult.NoMatch);
 }
Exemple #16
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);
    }
Exemple #17
0
 public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
 {
     System.Diagnostics.Debugger.Break();
     return(MatchResult.Matched);
 }
Exemple #18
0
 public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q)
 {
     if (frame.ListState == ListTermState.Start)
     {
         frame.ListState = ListTermState.MatchItem;
         stack.Push(ItemProd);
         return(null); // -> MatchItem
     }
     else if (frame.ListState == ListTermState.MatchSeparator)
     {
         var result = frame.SubResult;
         if (result.IsMatch)
         {
             // we have a separator.  now try to match the item following it.
             frame.ListState = ListTermState.MatchItem;
             stack.Push(ItemProd);
             return(null); // -> MatchItem
         }
         else if (result.ErrorMessage == null)
         {
             // we didn't find a separator.  this list is done.  back up to the beginning of where
             // the not-separator started and we're done.
             q.Jump(frame.ListSeparatorStartLoc);
             if (frame.ListCount < Min)
             {
                 return(MatchResult.Error(
                            $"At least {Min} list item{(Min == 1 ? " is" : "s are")} required, but only " +
                            $"{frame.ListCount} {(frame.ListCount == 1 ? "was" : "were")} provided. " +
                            $"Expected list item: {ItemProd.GetExpected()}"));
             }
             else
             {
                 return(MatchResult.Matched);
             }
         }
         else
         {
             return(result); // error
         }
     }
     else if (frame.ListState == ListTermState.MatchItem)
     {
         var result = frame.SubResult;
         if (result.IsMatch)
         {
             // we have an item.  is there another?
             frame.ListCount++;
             if (SeparatorProd == null)
             {
                 // there is no separator, so match the next item
                 frame.ListState             = ListTermState.MatchItem;
                 frame.ListSeparatorStartLoc = q.GetLocation();
                 stack.Push(ItemProd);
                 return(null); // -> MatchItem
             }
             else
             {
                 // match separator + item
                 frame.ListState             = ListTermState.MatchSeparator;
                 frame.ListSeparatorStartLoc = q.GetLocation();
                 stack.Push(SeparatorProd);
                 return(null); // -> MatchSeparator
             }
         }
         else if (result.ErrorMessage == null)
         {
             if (frame.ListCount == 0)
             {
                 // the first item might be missing because the list can potentially be optional.
                 return(Min == 0 ? MatchResult.Matched : MatchResult.NoMatch);
             }
             else if (SeparatorProd == null)
             {
                 // there's no separator, so eventually we'll end up here when the list ends.
                 q.Jump(frame.ListSeparatorStartLoc);
                 if (frame.ListCount < Min)
                 {
                     return(MatchResult.Error(
                                $"At least {Min} list item{(Min == 1 ? " is" : "s are")} required, but only " +
                                $"{frame.ListCount} {(frame.ListCount == 1 ? "was" : "were")} provided. " +
                                $"Expected list item: {ItemProd.GetExpected()}"));
                 }
                 else
                 {
                     return(MatchResult.Matched);
                 }
             }
             else
             {
                 // subsequent items must be present because, in the MatchItem state, we've already consumed a
                 // separator so there must be an item following it.
                 return(MatchResult.Error($"Expected list item: {ItemProd.GetExpected()}"));
             }
         }
         else
         {
             return(result); // error
         }
     }
     else
     {
         throw new Exception($"Unrecognized state: {frame.ListState}");
     }
 }