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; }
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(); }
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); } }
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); } }
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}"); } }
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); }
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(); } } }
public abstract MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q);
private object CurrentStackId() { return(MatchStack.Count == 0 ? null : MatchStack.Peek()); }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { return(q.Take().Text.ToLower() == Text.ToLower() ? MatchResult.Matched : MatchResult.NoMatch); }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { return(q.Take().Type == TokenType.String ? MatchResult.Matched : MatchResult.NoMatch); }
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); }
public override MatchResult?MatchStep(MatchStack stack, MatchFrame frame, TokenQueue q) { System.Diagnostics.Debugger.Break(); return(MatchResult.Matched); }
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}"); } }