From df77b84c90baf3e2b862e66f3efa340e379e0979 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Tue, 7 Jul 2026 02:56:50 -0400 Subject: [PATCH 01/48] Phase 0: static decision classifier + -Xdecision-report flag Adds tool/src/org/antlr/v4/analysis/DecisionClassifier.java: an exhaustive static SLL DFA constructor that classifies every parser decision by the lookahead machinery it requires to predict without adaptivePredict at runtime. Classification categories: - LL1 existing fast path (delegated to AnalysisPipeline.disjoint) - LLK acyclic SLL DFA, decidable in <=k tokens (k<=5 across SQL grammars) - LLSTAR cyclic SLL DFA, regular unbounded lookahead (ANTLR3-style) - EXACT_AMBIG exact+untainted ambiguity; min-alt is behavior-preserving - CONTEXT_SENSITIVE non-exact conflicts OR conflicts tainted by widening - PREDICATED lookahead traverses a semantic predicate - NON_GREEDY never statically predicted - LR_PRECEDENCE precedence loop of a left-recursive rule - OVERFLOW DFA exceeded the state/budget cap The classifier exhaustively constructs the SLL DFA the runtime would otherwise build lazily, reusing the runtime's ATNConfig/ATNConfigSet/ PredictionMode conflict machinery so verdicts match runtime SLL semantics. Token-interval equivalence classes serve as the alphabet (never per-token). Iterative deepening: exact construction first (widening only at direct call-site recursion, which yields cyclic LL(*) DFAs), falling back to a fully context-free approximation on overflow. A WIDENED_TAINT bit in ATNConfig.reachesIntoOuterContext marks configs whose calling context was widened; conflict states involving any tainted config are untrusted (demoted from EXACT_AMBIG to CONTEXT_SENSITIVE), because widened conflicts may be analysis artifacts that the runtime never encounters (cf. PERMUTE(a, b) in Bigquery's patternPrimary). Wiring: new -Xdecision-report flag in Tool.java prints the report after AnalysisPipeline. Default off; zero impact otherwise. Output includes per-decision category, k, dfaStates, conflict alt sets (exactAmbigAlts / ctxSensitiveAlts / approxConflictAlts), taint flags, an LLK k-histogram, and split max-k (LLK vs any acyclic non-LL(1) including conflicted). Signed-off-by: Bo Lin --- tool/src/org/antlr/v4/Tool.java | 7 + .../antlr/v4/analysis/DecisionClassifier.java | 668 ++++++++++++++++++ 2 files changed, 675 insertions(+) create mode 100644 tool/src/org/antlr/v4/analysis/DecisionClassifier.java diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index e98b7e0b5a..9af99573a9 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -13,6 +13,7 @@ import org.antlr.runtime.ParserRuleReturnScope; import org.antlr.runtime.RecognitionException; import org.antlr.v4.analysis.AnalysisPipeline; +import org.antlr.v4.analysis.DecisionClassifier; import org.antlr.v4.automata.ATNFactory; import org.antlr.v4.automata.LexerATNFactory; import org.antlr.v4.automata.ParserATNFactory; @@ -113,6 +114,7 @@ public Option(String fieldName, String name, OptionArgType argType, String descr public boolean warnings_are_errors = false; public boolean longMessages = false; public boolean exact_output_dir = false; + public boolean decision_report = false; public final static Option[] optionDefs = { new Option("outputDirectory", "-o", OptionArgType.STRING, "specify output directory where all output is generated"), @@ -136,6 +138,7 @@ public Option(String fieldName, String name, OptionArgType argType, String descr new Option("force_atn", "-Xforce-atn", "use the ATN simulator for all predictions"), new Option("log", "-Xlog", "dump lots of logging info to antlr-timestamp.log"), new Option("exact_output_dir", "-Xexact-output-dir", "all output goes into -o dir regardless of paths/package"), + new Option("decision_report", "-Xdecision-report", "classify every parser decision by required static lookahead (LL(1)/LL(k)/LL(*)/ambiguous/context-sensitive) and print a report"), }; // helper vars for option management @@ -406,6 +409,10 @@ public void processNonCombinedGrammar(Grammar g, boolean gencode) { if ( g.tool.getNumErrors()>prevErrors ) return; + if ( decision_report && !g.isLexer() ) { + System.out.print(DecisionClassifier.report(g)); + } + // GENERATE CODE if ( gencode ) { CodeGenPipeline gen = new CodeGenPipeline(g, codeGenerator); diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java new file mode 100644 index 0000000000..77bc8fc01b --- /dev/null +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.analysis; + +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNConfig; +import org.antlr.v4.runtime.atn.ATNConfigSet; +import org.antlr.v4.runtime.atn.ATNState; +import org.antlr.v4.runtime.atn.DecisionState; +import org.antlr.v4.runtime.atn.EmptyPredictionContext; +import org.antlr.v4.runtime.atn.LoopEndState; +import org.antlr.v4.runtime.atn.NotSetTransition; +import org.antlr.v4.runtime.atn.PrecedencePredicateTransition; +import org.antlr.v4.runtime.atn.PredicateTransition; +import org.antlr.v4.runtime.atn.PredictionContext; +import org.antlr.v4.runtime.atn.PredictionMode; +import org.antlr.v4.runtime.atn.RuleStopState; +import org.antlr.v4.runtime.atn.RuleTransition; +import org.antlr.v4.runtime.atn.SingletonPredictionContext; +import org.antlr.v4.runtime.atn.StarLoopEntryState; +import org.antlr.v4.runtime.atn.Transition; +import org.antlr.v4.runtime.atn.WildcardTransition; +import org.antlr.v4.runtime.misc.Interval; +import org.antlr.v4.runtime.misc.IntervalSet; +import org.antlr.v4.tool.Grammar; +import org.antlr.v4.tool.Rule; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collection; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +/** + * Classifies every parser decision by the kind of static lookahead + * machinery required to predict it without invoking {@code adaptivePredict} + * at runtime. + * + *

The classifier works by exhaustively constructing, at tool time, the SLL + * prediction DFA that {@link org.antlr.v4.runtime.atn.ParserATNSimulator} + * would otherwise build lazily at runtime. SLL prediction start states are + * context-free (the runtime computes them with a wildcard outer context and + * caches the resulting DFA across all invocation contexts), so the complete + * SLL DFA is statically computable. Conflict detection reuses the runtime's + * {@link PredictionMode} machinery so the verdicts match runtime SLL-mode + * behavior exactly.

+ * + *

Termination of the exhaustive construction is guaranteed by widening: + * when closure would push a rule-invocation follow state that already appears + * {@link #maxContextStateOccurrences} times in a configuration's calling + * context chain (i.e., recursion), the deeper stack is collapsed to the + * wildcard context. This over-approximates the exact SLL configuration space + * (it is what turns unbounded-lookahead decisions into cyclic DFAs + * instead of infinite ones), and results that relied on widening are marked + * {@link Result#usedWidening}.

+ */ +public class DecisionClassifier { + public enum Category { + /** SLL(1) with disjoint sets; the existing LL(1) codegen fast path applies. */ + LL1, + /** Acyclic SLL DFA; decidable with at most {@link Result#k} tokens of lookahead. */ + LLK, + /** Cyclic SLL DFA; decidable with unbounded but regular lookahead (ANTLR3-style LL(*)). */ + LLSTAR, + /** + * DFA construction reached one or more states where all viable + * alternatives conflict identically (an exact ambiguity), and none of + * the conflicting configurations descend from a widened (recursion- + * collapsed) context. Exactness over untainted configurations is + * preserved under any real outer context (the wildcard bottom is + * substituted uniformly across all alternatives), so this is a true + * grammar ambiguity: runtime SLL and full-context LL both resolve it + * to the minimum alternative, and a static min-alt resolution is + * behavior-preserving. + */ + EXACT_AMBIG, + /** + * DFA construction reached a conflict that cannot be trusted as an + * exact ambiguity: either a non-exact SLL conflict (runtime ALL(*) + * would retry with full context and may pick a different alternative + * than min-alt), or a conflict involving configurations tainted by + * widening (the conflict may be an analysis artifact that the runtime + * - even in SLL mode - never encounters, cf. PERMUTE(a, b) vs + * pattern-variable ambiguities). Static min-alt resolution at such + * states can reject or misparse inputs the runtime handles. + */ + CONTEXT_SENSITIVE, + /** Lookahead traverses a semantic predicate; not statically decidable. */ + PREDICATED, + /** Non-greedy decisions are never statically predicted. */ + NON_GREEDY, + /** The precedence loop decision of a left-recursive rule; stays on adaptivePredict. */ + LR_PRECEDENCE, + /** DFA construction exceeded {@link #maxDfaStates}. */ + OVERFLOW + } + + public static class Result { + public final DecisionState decisionState; + public Category category; + /** Max lookahead depth (tokens) if the DFA is acyclic; -1 if cyclic or unknown. */ + public int k = -1; + public int numDfaStates; + public boolean usedWidening; + /** + * Context-depth bound at which DFA construction converged + * (Integer.MAX_VALUE = exact construction, widened only at direct + * call-site recursion). + */ + public int wideningDepth = Integer.MAX_VALUE; + public boolean sawPredicate; + public boolean sawPrecPredicate; + /** Trusted exact ambiguities: exact conflicts over untainted configs; min-alt is behavior-preserving. */ + public final List exactAmbigConflicts = new ArrayList(); + /** Non-exact conflicts over untainted configs: genuine SLL/LL divergence candidates. */ + public final List contextSensitiveConflicts = new ArrayList(); + /** Conflicts involving widening-tainted configs: possibly analysis artifacts; untrusted. */ + public final List approxConflicts = new ArrayList(); + + public Result(DecisionState decisionState) { + this.decisionState = decisionState; + } + } + + /** + * Taint bits stored in {@link ATNConfig#reachesIntoOuterContext} marking + * configurations derived through an over-approximation. The field is + * chosen because every ATNConfig copy constructor propagates it, + * ATNConfigSet's merge takes the max of it, and equals/hashCode ignore it + * - so the taint flows to closure descendants and survives merging + * without affecting DFA state identity. (This classifier never uses the + * field's runtime meaning; note max-merge is bitwise-correct here only + * because tainted values compare greater than untainted ones and we only + * test for non-zero.) + * + *

Over-approximations are one-sided: they can only keep alternatives + * alive longer than the runtime would, so uniquely-predicted accepts + * remain correct, but a conflict involving tainted configurations may be + * an analysis artifact the runtime never encounters and must not be + * trusted as an exact ambiguity.

+ */ + protected static final int WIDENED_TAINT = 1; + + /** + * Taint for configurations that traversed a precedence predicate as + * epsilon (i.e., assumed {@code precpred(...)} true). Same one-sided + * soundness argument as {@link #WIDENED_TAINT}. + */ + protected static final int PRECPRED_TAINT = 2; + + /** All taint bits that make a conflict untrusted. */ + protected static final int ANY_TAINT = WIDENED_TAINT | PRECPRED_TAINT; + + /** Hard cap on DFA states per decision (per construction attempt). */ + public int maxDfaStates = 2000; + + /** + * Iterative-deepening schedule for the calling-context depth bound. The + * first attempt is exact (widening only at direct call-site recursion, + * which is required for termination and is what yields cyclic LL(*) + * DFAs); when an attempt overflows {@link #maxDfaStates}, construction is + * retried with progressively tighter widening. + * + *

Deep-but-not-recursive-through-the-same-call-site context chains + * (typical of expression precedence ladders) make the exact SLL + * configuration space explode combinatorially; bounding the depth + * collapses deeper stacks to the wildcard context. Depth 0 is the fully + * context-free approximation (ANTLR3-style linear approximate lookahead + * over token classes): every rule invocation keeps only its immediate + * return frame, which bounds the configuration space by construction. + * Widening errors are one-sided: a widened DFA can only produce spurious + * conflicts (resolved min-alt), never a wrong uniquely-predicted + * alternative.

+ */ + public int[] wideningDepths = { Integer.MAX_VALUE, 0 }; + + /** Wall-clock budget per construction attempt; exceeding it counts as overflow. */ + public long attemptBudgetMs = 5000; + + protected final Grammar g; + protected final ATN atn; + protected final IntervalSet allTokens; + + /** Depth bound of the construction attempt in progress. */ + protected int currentDepthBound = Integer.MAX_VALUE; + /** Per-attempt memo for {@link #contextDepth} (contexts share structure). */ + protected Map depthCache; + + public DecisionClassifier(Grammar g) { + this.g = g; + this.atn = g.atn; + this.allTokens = IntervalSet.of(Token.MIN_USER_TOKEN_TYPE, atn.maxTokenType); + } + + /** Classify all decisions of the grammar, indexed by decision number. */ + public List classifyAll() { + List results = new ArrayList(atn.decisionToState.size()); + for (DecisionState s : atn.decisionToState) { + results.add(classify(s)); + } + return results; + } + + public Result classify(DecisionState s) { + Result res = new Result(s); + if (s.nonGreedy) { + res.category = Category.NON_GREEDY; + return res; + } + if (isPrecedenceLoopDecision(s)) { + res.category = Category.LR_PRECEDENCE; + return res; + } + if (g.decisionLOOK != null && s.decision < g.decisionLOOK.size() + && AnalysisPipeline.disjoint(g.decisionLOOK.get(s.decision))) { + res.category = Category.LL1; + res.k = 1; + return res; + } + + // iterative deepening: exact first, then progressively wider approximation + Result last = res; + for (int depthBound : wideningDepths) { + Result attempt = new Result(s); + attempt.wideningDepth = depthBound; + if (!buildDFA(s, attempt, depthBound)) { + return attempt; + } + last = attempt; + } + last.category = Category.OVERFLOW; + return last; + } + + /** + * Replicates the runtime's ATNDeserializer#markPrecedenceDecisions logic + * on the tool-side ATN: the star loop entry of the operator loop that the + * left-recursion transformer generates. + */ + protected boolean isPrecedenceLoopDecision(DecisionState s) { + if (!(s instanceof StarLoopEntryState)) return false; + if (!atn.ruleToStartState[s.ruleIndex].isLeftRecursiveRule) return false; + ATNState maybeLoopEndState = s.transition(s.getNumberOfTransitions()-1).target; + if (!(maybeLoopEndState instanceof LoopEndState)) return false; + return maybeLoopEndState.epsilonOnlyTransitions + && maybeLoopEndState.transition(0).target instanceof RuleStopState; + } + + // --------------------------------------------------------------------- + // Static SLL DFA construction + // --------------------------------------------------------------------- + + /** One construction attempt at the given context-depth bound; true = overflow. */ + protected boolean buildDFA(DecisionState s, Result res, int depthBound) { + this.currentDepthBound = depthBound; + this.depthCache = new java.util.IdentityHashMap(); + Map, Integer> stateIds = new HashMap, Integer>(); + List> states = new ArrayList>(); + List> edges = new ArrayList>(); + List terminal = new ArrayList(); // accept or conflict; no expansion + + Set start = new LinkedHashSet(); + Set startBusy = new HashSet(); + for (int i = 0; i < s.getNumberOfTransitions(); i++) { + closure(new ATNConfig(s.transition(i).target, i+1, EmptyPredictionContext.Instance), + start, startBusy, res); + } + start = canonical(start); + stateIds.put(start, 0); + states.add(start); + edges.add(new ArrayList()); + terminal.add(Boolean.FALSE); + + Deque work = new ArrayDeque(); + work.add(0); + boolean overflow = false; + long deadline = System.currentTimeMillis() + attemptBudgetMs; + + while (!work.isEmpty() && !overflow) { + if (System.currentTimeMillis() > deadline) { overflow = true; break; } + int d = work.remove(); + Set configs = states.get(d); + ATNConfigSet cs = toConfigSet(configs); + + BitSet alts = PredictionMode.getAlts(cs); + if (alts.cardinality() <= 1) { + terminal.set(d, Boolean.TRUE); // accept (or dead) state + continue; + } + if (PredictionMode.hasSLLConflictTerminatingPrediction(PredictionMode.SLL, cs)) { + terminal.set(d, Boolean.TRUE); + Collection altSubsets = PredictionMode.getConflictingAltSubsets(cs); + boolean exact = PredictionMode.allSubsetsConflict(altSubsets) + && PredictionMode.allSubsetsEqual(altSubsets); + boolean tainted = false; + for (ATNConfig c : cs) { + if ((c.reachesIntoOuterContext & ANY_TAINT) != 0) { tainted = true; break; } + } + BitSet conflicting = PredictionMode.getAlts(altSubsets); + if (tainted) res.approxConflicts.add(conflicting); + else if (exact) res.exactAmbigConflicts.add(conflicting); + else res.contextSensitiveConflicts.add(conflicting); + continue; + } + + for (Set succ : successors(configs, res)) { + Integer id = stateIds.get(succ); + if (id == null) { + if (states.size() >= maxDfaStates) { overflow = true; break; } + id = states.size(); + stateIds.put(succ, id); + states.add(succ); + edges.add(new ArrayList()); + terminal.add(Boolean.FALSE); + work.add(id); + } + edges.get(d).add(id); + } + } + + res.numDfaStates = states.size(); + if (overflow) { + res.category = Category.OVERFLOW; + return true; + } + if (res.sawPredicate) { + res.category = Category.PREDICATED; + return false; + } + + boolean cyclic = isCyclic(edges); + if (!cyclic) res.k = longestPath(edges); + + if (!res.contextSensitiveConflicts.isEmpty() || !res.approxConflicts.isEmpty()) { + res.category = Category.CONTEXT_SENSITIVE; + } + else if (!res.exactAmbigConflicts.isEmpty()) res.category = Category.EXACT_AMBIG; + else if (cyclic) res.category = Category.LLSTAR; + else res.category = Category.LLK; + return false; + } + + /** + * Compute the distinct successor configuration sets of a DFA state, one + * per equivalence class of tokens (never per token). The labels + * themselves are not retained; Phase 0 only needs the DFA's shape. + */ + protected Collection> successors(Set configs, Result res) { + // collect non-epsilon moves + List labels = new ArrayList(); + List moveConfigs = new ArrayList(); + List moveTargets = new ArrayList(); + List moveIsStop = new ArrayList(); + for (ATNConfig c : configs) { + if (c.state instanceof RuleStopState) { + // Stop state with wildcard context: like the runtime's reach + // computation, such a config survives only the EOF symbol and + // is preserved verbatim (no closure past EOF). + labels.add(IntervalSet.of(Token.EOF)); + moveConfigs.add(c); + moveTargets.add(c.state); + moveIsStop.add(Boolean.TRUE); + continue; + } + for (int i = 0; i < c.state.getNumberOfTransitions(); i++) { + Transition t = c.state.transition(i); + if (t.isEpsilon()) continue; + IntervalSet label; + if (t instanceof NotSetTransition) { + label = ((NotSetTransition)t).set.complement(allTokens); + } + else if (t instanceof WildcardTransition) { + label = allTokens; + } + else { + label = t.label(); + } + if (label == null || label.isNil()) continue; + labels.add(label); + moveConfigs.add(c); + moveTargets.add(t.target); + moveIsStop.add(Boolean.FALSE); + } + } + + // partition the token space into equivalence classes over move labels + TreeSet boundaries = new TreeSet(); + for (IntervalSet label : labels) { + for (Interval iv : label.getIntervals()) { + boundaries.add(iv.a); + boundaries.add(iv.b+1); + } + } + + Map> byMoveKey = new LinkedHashMap>(); + for (int p : boundaries) { + BitSet key = new BitSet(labels.size()); + for (int m = 0; m < labels.size(); m++) { + if (labels.get(m).contains(p)) key.set(m); + } + if (key.isEmpty() || byMoveKey.containsKey(key)) continue; + Set succ = new LinkedHashSet(); + Set busy = new HashSet(); + for (int m = key.nextSetBit(0); m >= 0; m = key.nextSetBit(m+1)) { + ATNConfig c = moveConfigs.get(m); + if (moveIsStop.get(m)) { + succ.add(c); + } + else { + closure(new ATNConfig(c, moveTargets.get(m)), succ, busy, res); + } + } + byMoveKey.put(key, canonical(succ)); + } + // distinct successor sets (different token classes may close to the same set) + return new LinkedHashSet>(byMoveKey.values()); + } + + /** + * SLL epsilon closure, mirroring ParserATNSimulator's closure: predicates + * are traversed (and recorded), rule invocations push a singleton context + * (widened on recursion), rule stops pop or - with a wildcard context - + * chase the grammar-wide FOLLOW links the tool attaches to rule stop states. + */ + protected void closure(ATNConfig config, Set configs, Set busy, Result res) { + if (!busy.add(config)) return; + ATNState p = config.state; + + if (p instanceof RuleStopState) { + PredictionContext ctx = config.context; + if (ctx != null && !ctx.isEmpty()) { + for (int i = 0; i < ctx.size(); i++) { + if (ctx.getReturnState(i) == PredictionContext.EMPTY_RETURN_STATE) { + closure(new ATNConfig(config, p, EmptyPredictionContext.Instance), configs, busy, res); + } + else { + ATNState returnState = atn.states.get(ctx.getReturnState(i)); + closure(new ATNConfig(config, returnState, ctx.getParent(i)), configs, busy, res); + } + } + return; + } + // Wildcard context: keep the stop-state config (it participates in + // stop-state conflict detection and matches EOF), and additionally + // chase FOLLOW links via the epsilon transitions below. + configs.add(config); + } + + if (!p.onlyHasEpsilonTransitions()) { + configs.add(config); + } + + for (int i = 0; i < p.getNumberOfTransitions(); i++) { + Transition t = p.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + int followStateNumber = rt.followState.stateNumber; + PredictionContext newCtx; + boolean widened = false; + if (currentDepthBound == 0) { + // context-free approximation: no frames at all, returns + // resolve through the grammar-wide FOLLOW links + widened = true; + newCtx = EmptyPredictionContext.Instance; + } + else if (contextDepth(config.context) >= currentDepthBound + || hasReturnState(config.context, followStateNumber)) { + // call-site recursion or depth bound reached: keep the + // immediate return but widen the remaining stack to the + // wildcard context + widened = true; + newCtx = SingletonPredictionContext.create(EmptyPredictionContext.Instance, followStateNumber); + } + else { + newCtx = SingletonPredictionContext.create(config.context, followStateNumber); + } + ATNConfig callee = new ATNConfig(config, rt.target, newCtx); + if (widened) { + res.usedWidening = true; + callee.reachesIntoOuterContext |= WIDENED_TAINT; + } + closure(callee, configs, busy, res); + } + else if (t instanceof PrecedencePredicateTransition) { + // traversed as epsilon = assumed true: over-approximation + res.sawPrecPredicate = true; + ATNConfig c2 = new ATNConfig(config, t.target); + c2.reachesIntoOuterContext |= PRECPRED_TAINT; + closure(c2, configs, busy, res); + } + else if (t instanceof PredicateTransition) { + res.sawPredicate = true; + closure(new ATNConfig(config, t.target), configs, busy, res); + } + else if (t.isEpsilon()) { + closure(new ATNConfig(config, t.target), configs, busy, res); + } + } + } + + /** Does a return state appear anywhere in a (possibly DAG-shaped) context? */ + protected static boolean hasReturnState(PredictionContext ctx, int returnStateNumber) { + return hasReturnState(ctx, returnStateNumber, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); + } + + private static boolean hasReturnState(PredictionContext ctx, int returnStateNumber, Set visited) { + if (ctx == null || ctx.isEmpty() || !visited.add(ctx)) return false; + for (int i = 0; i < ctx.size(); i++) { + if (ctx.getReturnState(i) == returnStateNumber) return true; + if (ctx.getReturnState(i) != PredictionContext.EMPTY_RETURN_STATE + && hasReturnState(ctx.getParent(i), returnStateNumber, visited)) { + return true; + } + } + return false; + } + + /** Max chain length over any path of a (possibly DAG-shaped) context; memoized per attempt. */ + protected int contextDepth(PredictionContext ctx) { + if (ctx == null || ctx.isEmpty()) return 0; + Integer cached = depthCache.get(ctx); + if (cached != null) return cached; + int max = 0; + for (int i = 0; i < ctx.size(); i++) { + if (ctx.getReturnState(i) == PredictionContext.EMPTY_RETURN_STATE) continue; + max = Math.max(max, 1 + contextDepth(ctx.getParent(i))); + } + depthCache.put(ctx, max); + return max; + } + + protected static ATNConfigSet toConfigSet(Set configs) { + ATNConfigSet cs = new ATNConfigSet(false); + for (ATNConfig c : configs) cs.add(c); + return cs; + } + + /** + * Canonicalize a configuration set the way the runtime does: merge the + * contexts of configs that differ only in context (via ATNConfigSet), so + * DFA state identity matches the runtime's and recursive closures converge. + */ + protected static Set canonical(Set configs) { + return new LinkedHashSet(toConfigSet(configs).configs); + } + + protected static boolean isCyclic(List> edges) { + int n = edges.size(); + int[] color = new int[n]; // 0=white 1=gray 2=black + Deque stack = new ArrayDeque(); // {state, next edge index} + for (int root = 0; root < n; root++) { + if (color[root] != 0) continue; + stack.push(new int[]{root, 0}); + color[root] = 1; + while (!stack.isEmpty()) { + int[] frame = stack.peek(); + List out = edges.get(frame[0]); + if (frame[1] < out.size()) { + int t = out.get(frame[1]++); + if (color[t] == 1) return true; + if (color[t] == 0) { + color[t] = 1; + stack.push(new int[]{t, 0}); + } + } + else { + color[frame[0]] = 2; + stack.pop(); + } + } + } + return false; + } + + /** Longest path (#edges) from state 0 in an acyclic DFA = max lookahead depth. */ + protected static int longestPath(List> edges) { + int[] memo = new int[edges.size()]; + java.util.Arrays.fill(memo, -1); + return longestPathFrom(0, edges, memo); + } + + private static int longestPathFrom(int s, List> edges, int[] memo) { + if (memo[s] >= 0) return memo[s]; + memo[s] = 0; // also guards (unreachable in acyclic graphs) + int max = 0; + for (int t : edges.get(s)) { + max = Math.max(max, 1 + longestPathFrom(t, edges, memo)); + } + memo[s] = max; + return max; + } + + // --------------------------------------------------------------------- + // Report + // --------------------------------------------------------------------- + + /** Build the human-readable report printed by the -Xdecision-report tool option. */ + public static String report(Grammar g) { + DecisionClassifier classifier = new DecisionClassifier(g); + List results = classifier.classifyAll(); + + Map counts = new LinkedHashMap(); + for (Category c : Category.values()) counts.put(c, 0); + for (Result r : results) counts.put(r.category, counts.get(r.category)+1); + + StringBuilder buf = new StringBuilder(); + buf.append("=== decision report: grammar ").append(g.name) + .append(" (").append(results.size()).append(" decisions) ===\n"); + buf.append("summary:"); + for (Map.Entry e : counts.entrySet()) { + if (e.getValue() > 0) buf.append(' ').append(e.getKey()).append('=').append(e.getValue()); + } + buf.append('\n'); + + int maxKAnyAcyclic = 0; + int maxKLLK = 0; + Map llkHistogram = new java.util.TreeMap(); + for (Result r : results) { + if (r.category == Category.LL1 || r.category == Category.LR_PRECEDENCE) continue; + if (r.k > maxKAnyAcyclic) maxKAnyAcyclic = r.k; + if (r.category == Category.LLK) { + maxKLLK = Math.max(maxKLLK, r.k); + llkHistogram.merge(r.k, 1, Integer::sum); + } + Rule rule = g.getRule(r.decisionState.ruleIndex); + buf.append(String.format("%-22s d=%-4d %-17s", rule.name, r.decisionState.decision, r.category)); + if (r.k >= 0) buf.append(" k=").append(r.k); + buf.append(" dfaStates=").append(r.numDfaStates); + if (!r.exactAmbigConflicts.isEmpty()) { + buf.append(" exactAmbigAlts=").append(distinct(r.exactAmbigConflicts)); + } + if (!r.contextSensitiveConflicts.isEmpty()) { + buf.append(" ctxSensitiveAlts=").append(distinct(r.contextSensitiveConflicts)); + } + if (!r.approxConflicts.isEmpty()) { + buf.append(" approxConflictAlts=").append(distinct(r.approxConflicts)); + } + if (r.usedWidening) { + buf.append(r.wideningDepth == Integer.MAX_VALUE + ? " [widened]" : " [widened depth="+r.wideningDepth+"]"); + } + if (r.sawPrecPredicate) buf.append(" [precpred-in-lookahead]"); + buf.append('\n'); + } + buf.append("LLK k histogram: ").append(llkHistogram).append('\n'); + buf.append("max k: LLK=").append(maxKLLK) + .append(", any acyclic non-LL(1) (incl. conflicted)=").append(maxKAnyAcyclic).append('\n'); + return buf.toString(); + } + + private static Set distinct(List sets) { + return new LinkedHashSet(sets); + } +} From a60f00396eedb92e4d0b67cfe9763ad00786f772 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Thu, 9 Jul 2026 17:39:29 -0400 Subject: [PATCH 02/48] Static SLL prediction tables: -Xstatic-dfa (phase 1) Generate table-driven prediction for every parser decision whose static resolution is provably behavior-preserving, eliminating adaptivePredict from ~82-94% of non-LR decisions in real-world SQL grammars. Covered classes: LL(k) decisions (k<=5 in practice), cyclic LL(*) decisions (e.g. dotted-name scanning), and trusted exact ambiguities (resolved min-alt, identical to runtime SLL/LL). Unsafe residues (context- sensitive, overflow, predicated, non-greedy, LR-precedence) keep adaptivePredict. Tool: - DecisionClassifier now captures fully-labeled prediction DFAs (StaticDFA) during classification and exposes buildTables(), which aborts a decision early at the first untrusted conflict; wired behind the opt-in -Xstatic-dfa flag (-Xforce-atn overrides). - New choice models DFAAltBlock/DFAOptionalBlock/DFAStarBlock/ DFAPlusBlock mirror the adaptive shapes with the prediction call swapped; gated by Target.supportsStaticDFA() (Java, Rust). - Tables serialize compactly via CompactSerializer: zigzag LEB128 varints, base64, 80-column line segments. Rust target: - The serialized ATN switches to the same compact encoding (SerializedBase64ATN), replacing the decimal int list; static DFA tables are appended inside the same blob. Both are decoded in one streaming pass (serialized_ints::Decoder, ATNDeserializer::deserialize_compact) into ATN::static_dfas, with no intermediate or retained Vec. - Prediction runs through BaseParser::dfa_predict(decision): a plain table walk over LA(1..n) - no ATN simulation, no per-prediction allocation, no shared DFA cache - with NoViableAlt semantics matching adaptive_predict. Java target (testing parity): - Separate _serializedStaticDFA blob deserialized at class init (atn.StaticDFATables) + Parser.dfaPredict walker; the standard serialized ATN format is unchanged. Generated output is byte-identical when the flag is off; with it on, parse trees and error messages are identical to adaptivePredict in all differential tests. New test grammar StaticDFA.g4 (LL(k), cyclic LL(*), non-LL(1) loop/optional decisions, exact ambiguity) is wired into gen_test_grammars.sh with -Xstatic-dfa, and tests/static_dfa_tests.rs exercises the full decode+predict path, asserting zero adaptive_predict call sites in the generated parser. Signed-off-by: Bo Lin --- .../Java/src/org/antlr/v4/runtime/Parser.java | 35 + .../antlr/v4/runtime/atn/StaticDFATables.java | 173 ++ runtime/Rust/gen_test_grammars.sh | 2 + runtime/Rust/grammars/StaticDFA.g4 | 34 + runtime/Rust/src/atn.rs | 8 + runtime/Rust/src/atn_deserializer.rs | 112 +- runtime/Rust/src/atn_simulator.rs | 5 + runtime/Rust/src/lib.rs | 2 + runtime/Rust/src/parser.rs | 41 +- runtime/Rust/src/serialized_ints.rs | 124 ++ runtime/Rust/src/static_dfa.rs | 183 ++ runtime/Rust/tests/gen/csvlexer.rs | 33 +- runtime/Rust/tests/gen/csvparser.rs | 27 +- runtime/Rust/tests/gen/labelslexer.rs | 39 +- runtime/Rust/tests/gen/labelsparser.rs | 35 +- runtime/Rust/tests/gen/referencetoatnlexer.rs | 20 +- .../Rust/tests/gen/referencetoatnparser.rs | 15 +- runtime/Rust/tests/gen/simplelrlexer.rs | 16 +- runtime/Rust/tests/gen/simplelrparser.rs | 16 +- .../Rust/tests/gen/staticdfabaselistener.rs | 143 ++ runtime/Rust/tests/gen/staticdfalexer.rs | 143 ++ runtime/Rust/tests/gen/staticdfalistener.rs | 114 + runtime/Rust/tests/gen/staticdfaparser.rs | 1833 +++++++++++++++++ runtime/Rust/tests/gen/visitorbasiclexer.rs | 10 +- runtime/Rust/tests/gen/visitorbasicparser.rs | 10 +- runtime/Rust/tests/gen/visitorcalclexer.rs | 27 +- runtime/Rust/tests/gen/visitorcalcparser.rs | 20 +- runtime/Rust/tests/gen/xmllexer.rs | 156 +- runtime/Rust/tests/static_dfa_tests.rs | 166 ++ .../v4/tool/templates/codegen/Java/Java.stg | 84 +- .../v4/tool/templates/codegen/Rust/Rust.stg | 86 +- tool/src/org/antlr/v4/Tool.java | 7 + .../antlr/v4/analysis/DecisionClassifier.java | 186 +- tool/src/org/antlr/v4/analysis/StaticDFA.java | 53 + .../antlr/v4/codegen/CompactSerializer.java | 69 + .../org/antlr/v4/codegen/ParserFactory.java | 40 + tool/src/org/antlr/v4/codegen/Target.java | 16 + .../antlr/v4/codegen/model/DFAAltBlock.java | 27 + .../v4/codegen/model/DFAOptionalBlock.java | 26 + .../antlr/v4/codegen/model/DFAPlusBlock.java | 28 + .../antlr/v4/codegen/model/DFAStarBlock.java | 28 + .../org/antlr/v4/codegen/model/Parser.java | 19 + .../antlr/v4/codegen/model/Recognizer.java | 3 + .../v4/codegen/model/SerializedBase64ATN.java | 53 + .../codegen/model/SerializedStaticDFAs.java | 87 + .../antlr/v4/codegen/target/JavaTarget.java | 3 + .../antlr/v4/codegen/target/RustTarget.java | 6 + tool/src/org/antlr/v4/tool/Grammar.java | 8 + 48 files changed, 4005 insertions(+), 366 deletions(-) create mode 100644 runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java create mode 100644 runtime/Rust/grammars/StaticDFA.g4 create mode 100644 runtime/Rust/src/serialized_ints.rs create mode 100644 runtime/Rust/src/static_dfa.rs create mode 100644 runtime/Rust/tests/gen/staticdfabaselistener.rs create mode 100644 runtime/Rust/tests/gen/staticdfalexer.rs create mode 100644 runtime/Rust/tests/gen/staticdfalistener.rs create mode 100644 runtime/Rust/tests/gen/staticdfaparser.rs create mode 100644 runtime/Rust/tests/static_dfa_tests.rs create mode 100644 tool/src/org/antlr/v4/analysis/StaticDFA.java create mode 100644 tool/src/org/antlr/v4/codegen/CompactSerializer.java create mode 100644 tool/src/org/antlr/v4/codegen/model/DFAAltBlock.java create mode 100644 tool/src/org/antlr/v4/codegen/model/DFAOptionalBlock.java create mode 100644 tool/src/org/antlr/v4/codegen/model/DFAPlusBlock.java create mode 100644 tool/src/org/antlr/v4/codegen/model/DFAStarBlock.java create mode 100644 tool/src/org/antlr/v4/codegen/model/SerializedBase64ATN.java create mode 100644 tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java index 34ab288108..274a2604fb 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java @@ -15,6 +15,7 @@ import org.antlr.v4.runtime.atn.PredictionMode; import org.antlr.v4.runtime.atn.ProfilingATNSimulator; import org.antlr.v4.runtime.atn.RuleTransition; +import org.antlr.v4.runtime.atn.StaticDFATables; import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.misc.IntegerStack; import org.antlr.v4.runtime.misc.IntervalSet; @@ -527,6 +528,40 @@ public Token getCurrentToken() { return _input.LT(1); } + /** + * Predict the alternative of a decision from a statically-precomputed + * SLL prediction DFA (generated by the tool's {@code -Xstatic-dfa} + * option) instead of {@code adaptivePredict}. Walks the decision's + * table in {@code tables} (deserialized once, at class initialization, + * from the compact blob embedded in the generated parser - in the same + * vein as {@code _serializedATN}) over {@code LA(1..n)} without + * consuming input; performs no ATN simulation and no per-prediction + * allocation. A lookahead token matching no edge is a + * no-viable-alternative error, reported against the token at the + * decision start exactly like {@code adaptivePredict}. + * + * @return the predicted alternative (1-based, decision-transition + * numbering identical to {@code adaptivePredict}) + */ + public int dfaPredict(StaticDFATables tables, int decision) + throws RecognitionException + { + int s = 0; + int i = 1; + while (true) { + int alt = tables.accept(decision, s); + if ( alt>0 ) return alt; + int next = tables.edge(decision, s, _input.LA(i)); + if ( next<0 ) { + throw new NoViableAltException(this, _input, + _input.LT(1), _input.LT(i), + null, _ctx); + } + s = next; + i++; + } + } + public final void notifyErrorListeners(String msg) { notifyErrorListeners(getCurrentToken(), msg, null); } diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java new file mode 100644 index 0000000000..00fb2294d4 --- /dev/null +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.runtime.atn; + +import java.util.Base64; + +/** + * The deserialized statically-precomputed SLL prediction tables of one + * generated parser (produced by the ANTLR tool's {@code -Xstatic-dfa} + * option). All of a parser's tables are packed into one compact serialized + * blob - in the same vein as {@code _serializedATN} - deserialized once at + * class initialization; predictions then run through + * {@link org.antlr.v4.runtime.Parser#dfaPredict} as a plain table walk with + * no ATN simulation and no per-prediction allocation. + * + *

Wire format: each logical value is zigzag-mapped + * ({@code (v << 1) ^ (v >> 31)}) and stored as an unsigned LEB128 varint; + * the byte stream is base64-encoded (standard alphabet) and split into + * string segments. Logical layout:

+ * + *
+ * FORMAT_VERSION
+ * numTables
+ * numDecisionSlots                  (max decision number + 1)
+ * for each table:
+ *   decision
+ *   numStates
+ *   numEdgeInts
+ *   accepts[numStates]              (predicted alt per state; 0 = non-accept)
+ *   edgeOffsets[numStates+1]        (index of each state's first edge int)
+ *   edges[numEdgeInts]              ((lo, hi, target) triples, lo-sorted per state)
+ * 
+ * + *

State 0 of each table is its start state; {@code accepts[s] > 0} marks + * a terminal accept state predicting that alternative (numbering identical + * to {@code adaptivePredict}'s return value). A lookahead token matching no + * edge means no viable alternative. Cyclic tables (LL(*) decisions) are + * walked by the same loop; termination is guaranteed because every step + * consumes one token of lookahead and the input is finite.

+ */ +public class StaticDFATables { + /** Must match the tool's SerializedStaticDFAs.FORMAT_VERSION. */ + public static final int FORMAT_VERSION = 2; + + /** Concatenated per-table data: accepts, edgeOffsets, edges. */ + protected final int[] data; + /** Per-table (acceptsAt, edgeOffsetsAt, edgesAt, endAt) indexes into {@link #data}. */ + protected final int[] metas; + /** decision number -> table index, or -1. */ + protected final int[] decisionToTable; + + protected StaticDFATables(int[] data, int[] metas, int[] decisionToTable) { + this.data = data; + this.metas = metas; + this.decisionToTable = decisionToTable; + } + + /** + * Deserialize the base64/varint segments emitted by the tool. Throws on + * malformed input or a format-version mismatch: the blob is generated + * together with the parser that embeds it, so any failure is a build + * inconsistency, not a runtime condition. + */ + public static StaticDFATables deserialize(String[] segments) { + StringBuilder joined = new StringBuilder(); + for (String segment : segments) joined.append(segment); + byte[] bytes = Base64.getDecoder().decode(joined.toString()); + + IntReader ints = new IntReader(bytes); + int version = ints.next(); + if (version != FORMAT_VERSION) { + throw new UnsupportedOperationException( + "static DFA table format version mismatch ("+version+" != "+FORMAT_VERSION+"): " + + "parser was generated with a different ANTLR tool version, please regenerate"); + } + int numTables = ints.next(); + int numSlots = ints.next(); + + int[] decisionToTable = new int[numSlots]; + java.util.Arrays.fill(decisionToTable, -1); + int[] metas = new int[numTables*4]; + + // first pass over structure requires data sizes; buffer grows as we read + IntBuffer data = new IntBuffer(); + for (int table = 0; table < numTables; table++) { + int decision = ints.next(); + int numStates = ints.next(); + int numEdgeInts = ints.next(); + decisionToTable[decision] = table; + + metas[table*4] = data.size; // acceptsAt + for (int i = 0; i < numStates; i++) data.add(ints.next()); + metas[table*4+1] = data.size; // edgeOffsetsAt + for (int i = 0; i < numStates+1; i++) data.add(ints.next()); + metas[table*4+2] = data.size; // edgesAt + for (int i = 0; i < numEdgeInts; i++) data.add(ints.next()); + metas[table*4+3] = data.size; // endAt + } + if (!ints.atEnd()) { + throw new IllegalStateException("trailing bytes in static DFA blob"); + } + return new StaticDFATables(data.toArray(), metas, decisionToTable); + } + + /** Predicted alternative if {@code state} of {@code decision}'s table accepts; else 0. */ + public int accept(int decision, int state) { + int acceptsAt = metas[decisionToTable[decision]*4]; + return data[acceptsAt+state]; + } + + /** Successor of {@code state} on token {@code t}, or -1 (binary search). */ + public int edge(int decision, int state, int t) { + int table = decisionToTable[decision]; + int edgeOffsetsAt = metas[table*4+1]; + int edgesAt = metas[table*4+2]; + int lo = data[edgeOffsetsAt+state]/3; + int hi = data[edgeOffsetsAt+state+1]/3 - 1; + while (lo <= hi) { + int mid = (lo+hi) >>> 1; + int at = edgesAt + mid*3; + if (t < data[at]) hi = mid-1; + else if (t > data[at+1]) lo = mid+1; + else return data[at+2]; + } + return -1; + } + + private static final class IntReader { + final byte[] bytes; + int at; + + IntReader(byte[] bytes) { this.bytes = bytes; } + + /** Read one logical value: un-zigzagged LEB128 varint. */ + int next() { + int value = 0; + int shift = 0; + while (true) { + byte b = bytes[at++]; + value |= (b & 0x7F) << shift; + if ((b & 0x80) == 0) break; + shift += 7; + } + return (value >>> 1) ^ -(value & 1); // un-zigzag + } + + boolean atEnd() { return at == bytes.length; } + } + + private static final class IntBuffer { + int[] data = new int[4096]; + int size; + + void add(int v) { + if (size == data.length) { + int[] bigger = new int[data.length*2]; + System.arraycopy(data, 0, bigger, 0, size); + data = bigger; + } + data[size++] = v; + } + + int[] toArray() { + int[] result = new int[size]; + System.arraycopy(data, 0, result, 0, size); + return result; + } + } +} diff --git a/runtime/Rust/gen_test_grammars.sh b/runtime/Rust/gen_test_grammars.sh index 9f1fad2e4e..1cd455637f 100755 --- a/runtime/Rust/gen_test_grammars.sh +++ b/runtime/Rust/gen_test_grammars.sh @@ -13,6 +13,7 @@ declare -a GRAMMARS=( "XMLLexer" "SimpleLR" "Labels" + "StaticDFA" # "FHIRPath" ) @@ -24,6 +25,7 @@ declare -a ADDITIONAL_ARGS=( "" "" "" + "-Xstatic-dfa" ) for i in "${!GRAMMARS[@]}"; do diff --git a/runtime/Rust/grammars/StaticDFA.g4 b/runtime/Rust/grammars/StaticDFA.g4 new file mode 100644 index 0000000000..3ab67e927a --- /dev/null +++ b/runtime/Rust/grammars/StaticDFA.g4 @@ -0,0 +1,34 @@ +/* + * Test grammar for -Xstatic-dfa: every non-LL(1) decision below is + * statically decidable, so the generated parser must contain no + * adaptive_predict call sites (verified by tests/static_dfa_tests.rs). + */ +grammar StaticDFA; + +// LL(2)/LL(3) alt block: keyword-pair alternatives +stat : 'create' 'table' ID #createTable + | 'create' 'view' ID #createView + | 'drop' 'table' ID #dropTable + ; + +// LL(*): cyclic DFA scans the dotted name; '(' vs anything-else decides +expr : name '(' ')' #call + | name #ref + ; +name : ID ('.' ID)* ; + +// non-LL(1) loop enter/exit decisions (k=2) +starLoop : ('a' 'b')* 'a' 'c' ; +plusLoop : ('a' 'b')+ 'a' 'c' ; + +// non-LL(1) optional (k=2) +opt : ('a' 'b')? 'a' 'c' ; + +// exact ambiguity: statically resolved to the minimum alternative, +// identical to runtime SLL/LL behavior +dup : 'd' 'e' #dupFirst + | 'd' 'e' #dupSecond + ; + +ID : [a-z]+ ; +WS : [ \t\r\n]+ -> skip ; diff --git a/runtime/Rust/src/atn.rs b/runtime/Rust/src/atn.rs index 389f05c04d..03dd8aac18 100644 --- a/runtime/Rust/src/atn.rs +++ b/runtime/Rust/src/atn.rs @@ -9,6 +9,7 @@ use crate::interval_set::IntervalSet; use crate::interval_set::IntervalSetBuf; use crate::lexer_action::LexerAction; use crate::ll1_analyzer::LL1Analyzer; +use crate::static_dfa::StaticDFATables; use crate::token::Token; use crate::token::{TOKEN_EOF, TOKEN_EPSILON}; use crate::transition::RuleTransition; @@ -42,6 +43,12 @@ pub struct ATN { pub rule_to_token_type: Vec, + /// Statically-precomputed SLL prediction tables (`-Xstatic-dfa`), + /// decoded from the section following the ATN in the serialized blob; + /// empty when the parser was generated without them. See + /// [`crate::static_dfa`]. + pub static_dfas: StaticDFATables, + states: Vec>>, } @@ -68,6 +75,7 @@ impl ATN { rule_to_start_state: Vec::new(), rule_to_stop_state: Vec::new(), rule_to_token_type: Vec::new(), + static_dfas: StaticDFATables::empty(), states: Vec::new(), } } diff --git a/runtime/Rust/src/atn_deserializer.rs b/runtime/Rust/src/atn_deserializer.rs index c0c2efa197..a3922eb255 100644 --- a/runtime/Rust/src/atn_deserializer.rs +++ b/runtime/Rust/src/atn_deserializer.rs @@ -1,5 +1,3 @@ -use std::slice::Iter; - use crate::atn::ATN; use crate::atn_deserialization_options::ATNDeserializationOptions; use crate::atn_state::ATNState; @@ -46,8 +44,21 @@ impl ATNDeserializer { } } - pub fn deserialize(&self, data: &mut Iter) -> ATN { - self.check_version(*data.next().unwrap()); + /// Deserialize an ATN - and, when present, the statically-precomputed + /// SLL prediction tables (`-Xstatic-dfa`) appended after it - from the + /// compact base64/varint segments emitted by the tool, in one streaming + /// pass with no intermediate buffer. + pub fn deserialize_compact(&self, segments: &[&str]) -> ATN { + let mut ints = crate::serialized_ints::Decoder::new(segments).peekable(); + let mut atn = self.deserialize(&mut ints); + if ints.peek().is_some() { + atn.static_dfas = crate::static_dfa::StaticDFATables::from_int_stream(&mut ints); + } + atn + } + + pub fn deserialize(&self, data: &mut impl Iterator) -> ATN { + self.check_version(data.next().unwrap()); let mut atn = self.read_atn(data); @@ -90,30 +101,30 @@ impl ATNDeserializer { } } - fn read_atn(&self, data: &mut Iter) -> ATN { + fn read_atn(&self, data: &mut impl Iterator) -> ATN { ATN::new_atn( match data.next() { Some(0) => ATNType::Lexer, Some(1) => ATNType::Parser, _ => panic!("invalid ATN type"), }, - *data.next().unwrap(), + data.next().unwrap(), ) } - fn read_states(&self, atn: &mut ATN, data: &mut Iter) { + fn read_states(&self, atn: &mut ATN, data: &mut impl Iterator) { // let loop_back_states = Vec::<(BaseATNState,i32)>::new(); // let end_states = Vec::<(BaseATNState,i32)>::new(); - let states_count = *data.next().unwrap(); + let states_count = data.next().unwrap(); atn.alloc_states(states_count as usize); for i in 0..states_count { - let state_type = *data.next().unwrap(); + let state_type = data.next().unwrap(); if state_type == ATNSTATE_INVALID_STATE_NUMBER { atn.add_state(self.state_factory(ATNSTATE_INVALID_TYPE, -1, i)); panic!("why invalid state serialized?"); } - let mut rule_index = *data.next().unwrap(); + let mut rule_index = data.next().unwrap(); if rule_index == 0xFFFF { rule_index = -1; } @@ -124,7 +135,7 @@ impl ATNDeserializer { | ATNStateType::StarBlockStart | ATNStateType::PlusBlockStart => { let end_state = state.get_decision_end_state_mut().unwrap(); - *end_state = atn.make_state_ref(*data.next().unwrap()); + *end_state = atn.make_state_ref(data.next().unwrap()); } ATNStateType::LoopEnd => { let LoopEndState { @@ -132,17 +143,17 @@ impl ATNDeserializer { .. } = state.try_as_mut().unwrap(); - *loop_back_state = atn.make_state_ref(*data.next().unwrap()); + *loop_back_state = atn.make_state_ref(data.next().unwrap()); } _ => (), } atn.add_state(state); } - let num_non_greedy = *data.next().unwrap(); + let num_non_greedy = data.next().unwrap(); //println!("num_non_greedy {}", num_non_greedy); for _ in 0..num_non_greedy { - let st = *data.next().unwrap(); + let st = data.next().unwrap(); if let Some(nongreedy) = atn.get_state_mut(st).get_nongreedy_decision_mut() { *nongreedy = true } @@ -150,9 +161,9 @@ impl ATNDeserializer { //if (supportsPrecedencePredicates) if true { - let num_precedence_states = *data.next().unwrap(); + let num_precedence_states = data.next().unwrap(); for _ in 0..num_precedence_states { - let st = *data.next().unwrap(); + let st = data.next().unwrap(); if let Some(RuleStartState { ref mut is_left_recursive, .. @@ -164,8 +175,8 @@ impl ATNDeserializer { } } - fn read_rules(&self, atn: &mut ATN, data: &mut Iter) { - let nrules = *data.next().unwrap() as usize; + fn read_rules(&self, atn: &mut ATN, data: &mut impl Iterator) { + let nrules = data.next().unwrap() as usize; // if atn.grammar_type == ATNType::LEXER { // atn.rule_to_token_type.resize(nrules, 0) // } @@ -173,9 +184,9 @@ impl ATNDeserializer { atn.rule_to_start_state .resize(nrules, ATNStateRef::invalid()); for i in 0..nrules { - atn.rule_to_start_state[i] = atn.make_state_ref(*data.next().unwrap()); + atn.rule_to_start_state[i] = atn.make_state_ref(data.next().unwrap()); if atn.grammar_type == ATNType::Lexer { - let token_type = *data.next().unwrap(); + let token_type = data.next().unwrap(); atn.rule_to_token_type.push(token_type); } @@ -202,29 +213,33 @@ impl ATNDeserializer { } } - fn read_modes(&self, atn: &mut ATN, data: &mut Iter) { - let nmodes = *data.next().unwrap(); + fn read_modes(&self, atn: &mut ATN, data: &mut impl Iterator) { + let nmodes = data.next().unwrap(); for _i in 0..nmodes { atn.mode_to_start_state - .push(atn.make_state_ref(*data.next().unwrap())); + .push(atn.make_state_ref(data.next().unwrap())); } } - fn read_sets(&self, _atn: &mut ATN, data: &mut Iter) -> Vec { - let nsets = *data.next().unwrap(); + fn read_sets( + &self, + _atn: &mut ATN, + data: &mut impl Iterator, + ) -> Vec { + let nsets = data.next().unwrap(); let mut sets = Vec::new(); for _i in 0..nsets { - let intervals = *data.next().unwrap(); + let intervals = data.next().unwrap(); let mut set = IntervalSetBuf::new(); // check if contains eof - if *data.next().unwrap() != 0 { + if data.next().unwrap() != 0 { set.add_one(-1) } for _ in 0..intervals { - set.add_range(*data.next().unwrap(), *data.next().unwrap()); + set.add_range(data.next().unwrap(), data.next().unwrap()); } sets.push(set); } @@ -232,16 +247,21 @@ impl ATNDeserializer { sets } - fn read_edges(&self, atn: &mut ATN, data: &mut Iter, sets: &[&'static IntervalSet]) { - let nedges = *data.next().unwrap(); + fn read_edges( + &self, + atn: &mut ATN, + data: &mut impl Iterator, + sets: &[&'static IntervalSet], + ) { + let nedges = data.next().unwrap(); for _i in 0..nedges { - let src = *data.next().unwrap(); - let trg = *data.next().unwrap(); - let ttype = *data.next().unwrap(); - let arg1 = *data.next().unwrap(); - let arg2 = *data.next().unwrap(); - let arg3 = *data.next().unwrap(); + let src = data.next().unwrap(); + let trg = data.next().unwrap(); + let ttype = data.next().unwrap(); + let arg1 = data.next().unwrap(); + let arg2 = data.next().unwrap(); + let arg3 = data.next().unwrap(); let transition = self.edge_factory( atn, @@ -328,10 +348,10 @@ impl ATNDeserializer { // } } - fn read_decisions(&self, atn: &mut ATN, _data: &mut Iter) { - let ndecisions = *_data.next().unwrap(); + fn read_decisions(&self, atn: &mut ATN, _data: &mut impl Iterator) { + let ndecisions = _data.next().unwrap(); for i in 0..ndecisions { - let s = atn.make_state_ref(*_data.next().unwrap()); + let s = atn.make_state_ref(_data.next().unwrap()); atn.decision_to_state.push(s); if let Some(decision) = unsafe { s.as_mut() }.get_decision_mut() { *decision = i @@ -339,15 +359,15 @@ impl ATNDeserializer { } } - fn read_lexer_actions(&self, atn: &mut ATN, _data: &mut Iter) { + fn read_lexer_actions(&self, atn: &mut ATN, _data: &mut impl Iterator) { //lexer actions are always supported here - let nactions = *_data.next().unwrap(); + let nactions = _data.next().unwrap(); for _i in 0..nactions { - let action_type = *_data.next().unwrap(); + let action_type = _data.next().unwrap(); - let data1 = *_data.next().unwrap(); - let data2 = *_data.next().unwrap(); + let data1 = _data.next().unwrap(); + let data2 = _data.next().unwrap(); let lexer_action = self.lexer_action_factory(action_type, data1, data2); @@ -355,7 +375,7 @@ impl ATNDeserializer { } } - fn mark_precedence_decisions(&self, _atn: &mut ATN, _data: &mut Iter) { + fn mark_precedence_decisions(&self, _atn: &mut ATN, _data: &mut impl Iterator) { let mut precedence_states = Vec::new(); for state in _atn.iter_states() { if let Some(StarLoopEntryState { .. }) = state.try_as() { @@ -389,7 +409,7 @@ impl ATNDeserializer { } } - fn verify_atn(&self, _atn: &mut ATN, _data: &mut Iter) { + fn verify_atn(&self, _atn: &mut ATN, _data: &mut impl Iterator) { //TODO } diff --git a/runtime/Rust/src/atn_simulator.rs b/runtime/Rust/src/atn_simulator.rs index 8e5d62a128..bd9bd0e54a 100644 --- a/runtime/Rust/src/atn_simulator.rs +++ b/runtime/Rust/src/atn_simulator.rs @@ -173,6 +173,11 @@ impl + 'static> ATNSimulatorMan { self.allocation_limit_bytes.load(Ordering::Relaxed) } + /// The ATN this manager was built around. + pub fn atn(&self) -> &'static ATN { + self.atn + } + #[allow(dead_code)] pub(crate) fn reset_dfa(&self) { let is_resetting = self.is_resetting.swap(true, Ordering::AcqRel); diff --git a/runtime/Rust/src/lib.rs b/runtime/Rust/src/lib.rs index a9789c0929..b82cf29fa4 100644 --- a/runtime/Rust/src/lib.rs +++ b/runtime/Rust/src/lib.rs @@ -103,6 +103,8 @@ pub mod lexer_atn_simulator; pub mod parser; pub mod parser_atn_simulator; mod prediction_mode; +pub mod serialized_ints; +pub mod static_dfa; pub mod token; pub mod trees; mod utils; diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 1c18de12dc..3033ec9e89 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -16,7 +16,7 @@ use crate::interval_set::IntervalSet; use crate::parser_atn_simulator::ParserATNSimulator; use crate::recognizer::{Actions, Recognizer}; use crate::rule_context::{states_stack, RuleContext as _}; -use crate::token::{Token, TOKEN_EOF}; +use crate::token::{OwningToken, Token, TOKEN_EOF}; use crate::token_factory::TokenFactory; use crate::token_stream::TokenStream; use crate::tree::{NodeKindType, ParseTreeListener, Tree as _, TreeNode}; @@ -468,6 +468,45 @@ where self.global_cache_threshold = threshold; } + /// Predict the alternative of a decision from its statically-precomputed + /// SLL prediction DFA (generated by the ANTLR tool's `-Xstatic-dfa` + /// option and decoded into [`crate::atn::ATN::static_dfas`] together + /// with the ATN) instead of `adaptive_predict`. Walks the table over + /// `LA(1..n)` without consuming input; no ATN simulation, no + /// per-prediction allocation. + /// + /// Returns the predicted alternative (1-based, decision-transition + /// numbering identical to `adaptive_predict`). A lookahead token + /// matching no table edge produces a `NoViableAlt` error anchored at the + /// decision start token, matching `adaptive_predict`'s convention. + pub fn dfa_predict(&mut self, decision: i32) -> Result { + let dfa = self.atn_manager.atn().static_dfas.table(decision); + let mut s = 0usize; + let mut i = 1isize; + loop { + if let Some(alt) = dfa.accept(s) { + return Ok(alt); + } + let t = self.input.la(i); + match dfa.edge(s, t) { + Some(next) => { + s = next; + i += 1; + } + None => { + let start = self.input.lt(1).map(|t| OwningToken::from(t as &dyn Token)); + let offending = self.input.lt(i).map(|t| OwningToken::from(t as &dyn Token)); + return Err(match (start, offending) { + (Some(start), Some(offending)) => { + ANTLRError::no_alt_full(self, start, offending) + } + _ => ANTLRError::no_alt(self), + }); + } + } + } + } + pub fn get_interpreter_mut(&mut self) -> &mut ParserATNSimulator<'arena> { self.interp.as_mut().unwrap() } diff --git a/runtime/Rust/src/serialized_ints.rs b/runtime/Rust/src/serialized_ints.rs new file mode 100644 index 0000000000..607041573d --- /dev/null +++ b/runtime/Rust/src/serialized_ints.rs @@ -0,0 +1,124 @@ +//! Decoding of compact serialized integer streams embedded in generated +//! code (the tool's `CompactSerializer`): each value is zigzag-mapped, +//! LEB128-varint encoded, and the byte stream is base64-encoded and split +//! into string segments (rendered as one ~80-column literal per line). +//! +//! Used for the Rust target's `_serializedATN`, which carries the ATN +//! followed by the optional static DFA prediction tables (`-Xstatic-dfa`) +//! as a trailing section; both are decoded in one streaming pass with no +//! intermediate buffers. Decoding failures panic: these blobs are generated +//! together with the code that embeds them, so any failure is a build +//! inconsistency, not a runtime condition. + +/// A streaming decoder over base64/zigzag-varint segments, yielding the +/// original integer stream one value at a time. +pub struct Decoder<'a> { + segments: &'a [&'a str], + segment: usize, + at: usize, + /// Base64 bit accumulator. + acc: u32, + bits: u32, +} + +impl<'a> Decoder<'a> { + pub fn new(segments: &'a [&'a str]) -> Self { + Self { + segments, + segment: 0, + at: 0, + acc: 0, + bits: 0, + } + } + + /// Next byte of the base64-decoded stream, if any. + fn next_byte(&mut self) -> Option { + while self.bits < 8 { + let c = loop { + match self.segments.get(self.segment) { + None => return None, + Some(segment) => match segment.as_bytes().get(self.at) { + None => { + self.segment += 1; + self.at = 0; + } + Some(&c) => { + self.at += 1; + break c; + } + }, + } + }; + let v = match c { + b'A'..=b'Z' => c - b'A', + b'a'..=b'z' => c - b'a' + 26, + b'0'..=b'9' => c - b'0' + 52, + b'+' => 62, + b'/' => 63, + b'=' => continue, + _ => panic!("invalid base64 character in serialized data: {}", c as char), + }; + self.acc = (self.acc << 6) | v as u32; + self.bits += 6; + } + self.bits -= 8; + Some((self.acc >> self.bits) as u8) + } +} + +impl<'a> Iterator for Decoder<'a> { + type Item = i32; + + /// Next logical value: un-zigzagged LEB128 varint. + fn next(&mut self) -> Option { + let mut value: u32 = 0; + let mut shift = 0; + let mut first = true; + loop { + let b = match self.next_byte() { + Some(b) => b, + None if first => return None, + None => panic!("truncated varint in serialized data"), + }; + first = false; + value |= ((b & 0x7F) as u32) << shift; + if b & 0x80 == 0 { + break; + } + shift += 7; + } + // un-zigzag + Some(((value >> 1) as i32) ^ -((value & 1) as i32)) + } +} + +/// Decode all segments into a vector (convenience/testing; prefer streaming +/// via [`Decoder`] in production paths). +pub fn decode(segments: &[&str]) -> Vec { + Decoder::new(segments).collect() +} + +#[cfg(test)] +mod test { + use super::decode; + + #[test] + fn round_trip_reference() { + // encoded by the tool's CompactSerializer for [0, -1, 1, 300, -300, 123456789] + let segments = ["AAEC2ATXBKq03nU="]; + assert_eq!(decode(&segments), vec![0, -1, 1, 300, -300, 123456789]); + } + + #[test] + fn multi_segment() { + // same stream split mid-varint across segments + let segments = ["AAEC2AT", "XBKq03nU="]; + assert_eq!(decode(&segments), vec![0, -1, 1, 300, -300, 123456789]); + } + + #[test] + fn empty() { + assert_eq!(decode(&[]), Vec::::new()); + } +} diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs new file mode 100644 index 0000000000..00d7c7a5a4 --- /dev/null +++ b/runtime/Rust/src/static_dfa.rs @@ -0,0 +1,183 @@ +//! Table-driven static SLL prediction. +//! +//! The ANTLR tool's `-Xstatic-dfa` option precomputes, at code-generation +//! time, the SLL prediction DFAs that `ParserATNSimulator` would otherwise +//! build lazily at runtime - for every decision where the static resolution +//! is provably behavior-preserving (conflict-free LL(k)/LL(*) decisions and +//! trusted exact ambiguities resolved to the minimum alternative). +//! +//! All of a parser's tables are appended to the compact `_serializedATN` +//! blob and decoded together with the ATN in one streaming pass (see +//! `ATNDeserializer::deserialize_compact`), landing in +//! [`crate::atn::ATN::static_dfas`]. Predictions then run through +//! [`crate::parser::BaseParser::dfa_predict`]: a plain table walk over +//! `LA(1..n)` with no ATN simulation and no per-prediction allocation. +//! +//! The blob is encoded with the scheme in [`crate::serialized_ints`]; +//! the logical int stream layout of the tables section is: +//! +//! ```text +//! FORMAT_VERSION +//! numTables +//! numDecisionSlots (max decision number + 1) +//! for each table: +//! decision +//! numStates +//! numEdgeInts +//! accepts[numStates] (predicted alt per state; 0 = non-accept) +//! edgeOffsets[numStates+1] (index of each state's first edge i32) +//! edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) +//! ``` + +/// Format version understood by this runtime; must match the tool's +/// `SerializedStaticDFAs.FORMAT_VERSION`. +pub const FORMAT_VERSION: i32 = 2; + +/// The deserialized static prediction tables of one generated parser. +/// +/// Table data is stored in a single flat buffer; per-decision lookup is a +/// direct index. State `0` of each table is its start state; +/// `accepts[s] > 0` marks a terminal accept state predicting that +/// alternative (numbering identical to `adaptive_predict`'s return value). +/// A lookahead token matching no edge means no viable alternative. +/// +/// Cyclic tables (LL(*) decisions, e.g. dotted-name scanning) are walked by +/// exactly the same loop: termination is guaranteed because every step +/// consumes one token of lookahead and the input is finite (EOF included in +/// the token space). +pub struct StaticDFATables { + /// Concatenated per-table data: accepts, edge_offsets, edges. + data: Vec, + /// Per-table (accepts_at, edge_offsets_at, edges_at) indexes into `data`. + metas: Vec<(usize, usize, usize)>, + /// decision number -> table index, or -1. + decision_to_table: Vec, +} + +/// Borrowed view of one decision's table. +#[derive(Copy, Clone)] +pub struct StaticDFATable<'a> { + /// Predicted alternative per state; 0 = not an accept state. + pub accepts: &'a [i32], + /// Index of each state's first edge `i32` in `edges`; `num_states + 1` entries. + pub edge_offsets: &'a [i32], + /// Flattened `(lo, hi, target)` triples, sorted by `lo` within each state. + pub edges: &'a [i32], +} + +impl StaticDFATables { + /// No tables: every lookup fails; only reachable from hand-written code + /// since generated parsers only call `dfa_predict` for decisions they + /// serialized tables for. + pub fn empty() -> Self { + Self { + data: Vec::new(), + metas: Vec::new(), + decision_to_table: Vec::new(), + } + } + + /// Build the tables from the (already varint-decoded) logical int + /// stream, consuming it to the end - used by + /// `ATNDeserializer::deserialize_compact` for the section that follows + /// the ATN in the combined blob. + /// + /// Panics on malformed input or a format-version mismatch: the blob is + /// generated together with the parser that embeds it, so any failure is + /// a build inconsistency, not a runtime condition. + pub fn from_int_stream(ints: &mut impl Iterator) -> Self { + let mut next = || ints.next().expect("truncated static DFA table data"); + + let version = next(); + assert_eq!( + version, FORMAT_VERSION, + "static DFA table format version mismatch: parser was generated \ + with a different ANTLR tool version, please regenerate" + ); + let num_tables = next() as usize; + let num_slots = next() as usize; + + let mut data = Vec::new(); + let mut metas = Vec::with_capacity(num_tables); + let mut decision_to_table = vec![-1i32; num_slots]; + + for table in 0..num_tables { + let decision = next() as usize; + let num_states = next() as usize; + let num_edge_ints = next() as usize; + decision_to_table[decision] = table as i32; + + let accepts_at = data.len(); + for _ in 0..num_states { + data.push(next()); + } + let edge_offsets_at = data.len(); + for _ in 0..num_states + 1 { + data.push(next()); + } + let edges_at = data.len(); + for _ in 0..num_edge_ints { + data.push(next()); + } + metas.push((accepts_at, edge_offsets_at, edges_at)); + } + drop(next); + assert!(ints.next().is_none(), "trailing data in static DFA blob"); + + Self { + data, + metas, + decision_to_table, + } + } + + /// The table for a decision; panics if the decision has no static table + /// (generated code only references decisions it has tables for). + #[inline] + pub fn table(&self, decision: i32) -> StaticDFATable<'_> { + let t = self.decision_to_table[decision as usize]; + assert!(t >= 0, "no static DFA table for decision {}", decision); + let (accepts_at, edge_offsets_at, edges_at) = self.metas[t as usize]; + let end = self + .metas + .get(t as usize + 1) + .map(|m| m.0) + .unwrap_or(self.data.len()); + StaticDFATable { + accepts: &self.data[accepts_at..edge_offsets_at], + edge_offsets: &self.data[edge_offsets_at..edges_at], + edges: &self.data[edges_at..end], + } + } +} + +impl<'a> StaticDFATable<'a> { + /// Predicted alternative if `state` is an accept state. + #[inline] + pub fn accept(&self, state: usize) -> Option { + let alt = self.accepts[state]; + if alt > 0 { + Some(alt) + } else { + None + } + } + + /// Successor of `state` on token type `t`, if any (binary search). + #[inline] + pub fn edge(&self, state: usize, t: i32) -> Option { + let mut lo = (self.edge_offsets[state] / 3) as usize; + let mut hi = (self.edge_offsets[state + 1] / 3) as usize; + while lo < hi { + let mid = lo + (hi - lo) / 2; + if t < self.edges[mid * 3] { + hi = mid; + } else if t > self.edges[mid * 3 + 1] { + lo = mid + 1; + } else { + return Some(self.edges[mid * 3 + 2] as usize); + } + } + None + } +} diff --git a/runtime/Rust/tests/gen/csvlexer.rs b/runtime/Rust/tests/gen/csvlexer.rs index 8af12441ab..076b70abbf 100644 --- a/runtime/Rust/tests/gen/csvlexer.rs +++ b/runtime/Rust/tests/gen/csvlexer.rs @@ -113,26 +113,13 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 0, 6, 42, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, - 2, 4, 7, 4, 2, 5, 7, 5, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 4, - 3, 21, 8, 3, 11, 3, 12, 3, 22, 1, 3, 1, 3, 1, 4, 4, 4, 28, 8, 4, 11, - 4, 12, 4, 29, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 36, 8, 5, 10, 5, 12, 5, - 39, 9, 5, 1, 5, 1, 5, 0, 0, 6, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, - 1, 0, 3, 1, 0, 32, 32, 5, 0, 10, 10, 13, 13, 32, 32, 34, 34, 44, 44, - 1, 0, 34, 34, 45, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, - 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 1, 13, 1, - 0, 0, 0, 3, 15, 1, 0, 0, 0, 5, 17, 1, 0, 0, 0, 7, 20, 1, 0, 0, 0, 9, - 27, 1, 0, 0, 0, 11, 31, 1, 0, 0, 0, 13, 14, 5, 44, 0, 0, 14, 2, 1, 0, - 0, 0, 15, 16, 5, 13, 0, 0, 16, 4, 1, 0, 0, 0, 17, 18, 5, 10, 0, 0, 18, - 6, 1, 0, 0, 0, 19, 21, 7, 0, 0, 0, 20, 19, 1, 0, 0, 0, 21, 22, 1, 0, - 0, 0, 22, 20, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, - 25, 6, 3, 0, 0, 25, 8, 1, 0, 0, 0, 26, 28, 8, 1, 0, 0, 27, 26, 1, 0, - 0, 0, 28, 29, 1, 0, 0, 0, 29, 27, 1, 0, 0, 0, 29, 30, 1, 0, 0, 0, 30, - 10, 1, 0, 0, 0, 31, 37, 5, 34, 0, 0, 32, 33, 5, 34, 0, 0, 33, 36, 5, - 34, 0, 0, 34, 36, 8, 2, 0, 0, 35, 32, 1, 0, 0, 0, 35, 34, 1, 0, 0, 0, - 36, 39, 1, 0, 0, 0, 37, 35, 1, 0, 0, 0, 37, 38, 1, 0, 0, 0, 38, 40, - 1, 0, 0, 0, 39, 37, 1, 0, 0, 0, 40, 41, 5, 34, 0, 0, 41, 12, 1, 0, 0, - 0, 5, 0, 22, 29, 35, 37, 1, 0, 1, 0 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 7] = [ + "CAAMVAwBBAAOAAQCDgIEBA4EBAYOBgQIDggECg4KAgACAAICAgICBAIEAgYIBioQBhYGGAYsAgYCBgII", + "CAg4EAgWCBgIOgIKAgoCCgIKCgpIEAoUChgKThIKAgoCCgAADAICBgQKBg4IEgoWDAIABgIAQEAKABQU", + "GhpAQEREWFgCAEREWgACAgAAAAAGAgAAAAAKAgAAAAAOAgAAAAASAgAAAAAWAgAAAAIaAgAAAAYeAgAA", + "AAoiAgAAAA4oAgAAABI2AgAAABY+AgAAABocClgAABwEAgAAAB4gChoAACAIAgAAACIkChQAACQMAgAA", + "ACYqDgAAACgmAgAAACosAgAAACwoAgAAACwuAgAAAC4wAgAAADAyDAYAADIQAgAAADQ4EAIAADY0AgAA", + "ADg6AgAAADo2AgAAADo8AgAAADwUAgAAAD5KCkQAAEBCCkQAAEJICkQAAERIEAQAAEZAAgAAAEZEAgAA", + "AEhOAgAAAEpGAgAAAEpMAgAAAExQAgAAAE5KAgAAAFBSCkQAAFIYAgAAAAoALDpGSgIAAgA=" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/csvparser.rs b/runtime/Rust/tests/gen/csvparser.rs index 69ae3a1ea3..dae889368f 100644 --- a/runtime/Rust/tests/gen/csvparser.rs +++ b/runtime/Rust/tests/gen/csvparser.rs @@ -689,21 +689,12 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 1, 6, 35, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 1, 0, 1, - 0, 4, 0, 11, 8, 0, 11, 0, 12, 0, 12, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 5, - 2, 20, 8, 2, 10, 2, 12, 2, 23, 9, 2, 1, 2, 3, 2, 26, 8, 2, 1, 2, 1, - 2, 1, 3, 1, 3, 1, 3, 3, 3, 33, 8, 3, 1, 3, 0, 0, 4, 0, 2, 4, 6, 0, 0, - 35, 0, 8, 1, 0, 0, 0, 2, 14, 1, 0, 0, 0, 4, 16, 1, 0, 0, 0, 6, 32, 1, - 0, 0, 0, 8, 10, 3, 2, 1, 0, 9, 11, 3, 4, 2, 0, 10, 9, 1, 0, 0, 0, 11, - 12, 1, 0, 0, 0, 12, 10, 1, 0, 0, 0, 12, 13, 1, 0, 0, 0, 13, 1, 1, 0, - 0, 0, 14, 15, 3, 4, 2, 0, 15, 3, 1, 0, 0, 0, 16, 21, 3, 6, 3, 0, 17, - 18, 5, 1, 0, 0, 18, 20, 3, 6, 3, 0, 19, 17, 1, 0, 0, 0, 20, 23, 1, 0, - 0, 0, 21, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 25, 1, 0, 0, 0, 23, - 21, 1, 0, 0, 0, 24, 26, 5, 2, 0, 0, 25, 24, 1, 0, 0, 0, 25, 26, 1, 0, - 0, 0, 26, 27, 1, 0, 0, 0, 27, 28, 5, 3, 0, 0, 28, 5, 1, 0, 0, 0, 29, - 33, 5, 5, 0, 0, 30, 33, 5, 6, 0, 0, 31, 33, 1, 0, 0, 0, 32, 29, 1, 0, - 0, 0, 32, 30, 1, 0, 0, 0, 32, 31, 1, 0, 0, 0, 33, 7, 1, 0, 0, 0, 4, - 12, 21, 25, 32 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 6] = [ + "CAIMRgQADgAEAg4CBAQOBAQGDgYCAAIACAAWEAAWABgAGAICAgICBAIEAgQKBCgQBBQEGAQuEgQCBAYE", + "NBAEAgQCBAIGAgYCBgYGQhAGAgYAAAgABAgMAABGABACAAAABBwCAAAACCACAAAADEACAAAAEBQGBAIA", + "EhYGCAQAFBICAAAAFhgCAAAAGBQCAAAAGBoCAAAAGgICAAAAHB4GCAQAHgYCAAAAICoGDAYAIiQKAgAA", + "JCgGDAYAJiICAAAAKC4CAAAAKiYCAAAAKiwCAAAALDICAAAALioCAAAAMDQKBAAAMjACAAAAMjQCAAAA", + "NDYCAAAANjgKBgAAOAoCAAAAOkIKCgAAPEIKDAAAPkICAAAAQDoCAAAAQDwCAAAAQD4CAAAAQg4CAAAA", + "CBgqMkA=" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/labelslexer.rs b/runtime/Rust/tests/gen/labelslexer.rs index c4fbdbd73b..440d9efcdb 100644 --- a/runtime/Rust/tests/gen/labelslexer.rs +++ b/runtime/Rust/tests/gen/labelslexer.rs @@ -121,30 +121,15 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 0, 11, 55, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, - 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, - 9, 2, 10, 7, 10, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, - 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 4, 8, - 43, 8, 8, 11, 8, 12, 8, 44, 1, 9, 4, 9, 48, 8, 9, 11, 9, 12, 9, 49, - 1, 10, 1, 10, 1, 10, 1, 10, 0, 0, 11, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, - 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 1, 0, 1, 2, 0, 10, 10, 32, - 32, 56, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, - 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, - 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, - 0, 0, 1, 23, 1, 0, 0, 0, 3, 25, 1, 0, 0, 0, 5, 27, 1, 0, 0, 0, 7, 29, - 1, 0, 0, 0, 9, 31, 1, 0, 0, 0, 11, 33, 1, 0, 0, 0, 13, 35, 1, 0, 0, - 0, 15, 38, 1, 0, 0, 0, 17, 42, 1, 0, 0, 0, 19, 47, 1, 0, 0, 0, 21, 51, - 1, 0, 0, 0, 23, 24, 5, 123, 0, 0, 24, 2, 1, 0, 0, 0, 25, 26, 5, 125, - 0, 0, 26, 4, 1, 0, 0, 0, 27, 28, 5, 42, 0, 0, 28, 6, 1, 0, 0, 0, 29, - 30, 5, 43, 0, 0, 30, 8, 1, 0, 0, 0, 31, 32, 5, 40, 0, 0, 32, 10, 1, - 0, 0, 0, 33, 34, 5, 41, 0, 0, 34, 12, 1, 0, 0, 0, 35, 36, 5, 43, 0, - 0, 36, 37, 5, 43, 0, 0, 37, 14, 1, 0, 0, 0, 38, 39, 5, 45, 0, 0, 39, - 40, 5, 45, 0, 0, 40, 16, 1, 0, 0, 0, 41, 43, 2, 97, 122, 0, 42, 41, - 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 42, 1, 0, 0, 0, 44, 45, 1, 0, 0, - 0, 45, 18, 1, 0, 0, 0, 46, 48, 2, 48, 57, 0, 47, 46, 1, 0, 0, 0, 48, - 49, 1, 0, 0, 0, 49, 47, 1, 0, 0, 0, 49, 50, 1, 0, 0, 0, 50, 20, 1, 0, - 0, 0, 51, 52, 7, 0, 0, 0, 52, 53, 1, 0, 0, 0, 53, 54, 6, 10, 0, 0, 54, - 22, 1, 0, 0, 0, 3, 0, 44, 49, 1, 6, 0, 0 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 9] = [ + "CAAWbgwBBAAOAAQCDgIEBA4EBAYOBgQIDggECg4KBAwODAQODg4EEA4QBBIOEgQUDhQCAAIAAgICAgIE", + "AgQCBgIGAggCCAIKAgoCDAIMAgwCDgIOAg4CEAgQVhAQFhAYEFgCEggSYBASFhIYEmICFAIUAhQCFAAA", + "FgICBgQKBg4IEgoWDBoOHhAiEiYUKhYCAAIEABQUQEBwAAICAAAAAAYCAAAAAAoCAAAAAA4CAAAAABIC", + "AAAAABYCAAAAABoCAAAAAB4CAAAAACICAAAAACYCAAAAACoCAAAAAi4CAAAABjICAAAACjYCAAAADjoC", + "AAAAEj4CAAAAFkICAAAAGkYCAAAAHkwCAAAAIlQCAAAAJl4CAAAAKmYCAAAALjAK9gEAADAEAgAAADI0", + "CvoBAAA0CAIAAAA2OApUAAA4DAIAAAA6PApWAAA8EAIAAAA+QApQAABAFAIAAABCRApSAABEGAIAAABG", + "SApWAABISgpWAABKHAIAAABMTgpaAABOUApaAABQIAIAAABSVgTCAfQBAFRSAgAAAFZYAgAAAFhUAgAA", + "AFhaAgAAAFokAgAAAFxgBGByAF5cAgAAAGBiAgAAAGJeAgAAAGJkAgAAAGQoAgAAAGZoDgAAAGhqAgAA", + "AGpsDBQAAGwsAgAAAAYAWGICDAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/labelsparser.rs b/runtime/Rust/tests/gen/labelsparser.rs index b3e16de542..22edb68113 100644 --- a/runtime/Rust/tests/gen/labelsparser.rs +++ b/runtime/Rust/tests/gen/labelsparser.rs @@ -1431,27 +1431,14 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 1, 11, 49, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 3, 0, 12, 8, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 1, 24, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 42, - 8, 1, 10, 1, 12, 1, 45, 9, 1, 1, 2, 1, 2, 1, 2, 0, 1, 2, 3, 0, 2, 4, - 0, 0, 52, 0, 11, 1, 0, 0, 0, 2, 23, 1, 0, 0, 0, 4, 46, 1, 0, 0, 0, 6, - 12, 3, 2, 1, 0, 7, 8, 5, 1, 0, 0, 8, 9, 3, 4, 2, 0, 9, 10, 5, 2, 0, - 0, 10, 12, 1, 0, 0, 0, 11, 6, 1, 0, 0, 0, 11, 7, 1, 0, 0, 0, 12, 1, - 1, 0, 0, 0, 13, 14, 6, 1, -1, 0, 14, 15, 5, 10, 0, 0, 15, 24, 6, 1, - -1, 0, 16, 17, 5, 5, 0, 0, 17, 18, 3, 2, 1, 0, 18, 19, 5, 6, 0, 0, 19, - 20, 6, 1, -1, 0, 20, 24, 1, 0, 0, 0, 21, 22, 5, 9, 0, 0, 22, 24, 6, - 1, -1, 0, 23, 13, 1, 0, 0, 0, 23, 16, 1, 0, 0, 0, 23, 21, 1, 0, 0, 0, - 24, 43, 1, 0, 0, 0, 25, 26, 10, 7, 0, 0, 26, 27, 5, 3, 0, 0, 27, 28, - 3, 2, 1, 8, 28, 29, 6, 1, -1, 0, 29, 42, 1, 0, 0, 0, 30, 31, 10, 6, - 0, 0, 31, 32, 5, 4, 0, 0, 32, 33, 3, 2, 1, 7, 33, 34, 6, 1, -1, 0, 34, - 42, 1, 0, 0, 0, 35, 36, 10, 3, 0, 0, 36, 37, 5, 7, 0, 0, 37, 42, 6, - 1, -1, 0, 38, 39, 10, 2, 0, 0, 39, 40, 5, 8, 0, 0, 40, 42, 6, 1, -1, - 0, 41, 25, 1, 0, 0, 0, 41, 30, 1, 0, 0, 0, 41, 35, 1, 0, 0, 0, 41, 38, - 1, 0, 0, 0, 42, 45, 1, 0, 0, 0, 43, 41, 1, 0, 0, 0, 43, 44, 1, 0, 0, - 0, 44, 3, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 46, 47, 3, 0, 0, 0, 47, 5, - 1, 0, 0, 0, 4, 11, 23, 41, 43 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 8] = [ + "CAIWYgQADgAEAg4CBAQOBAIAAgACAAIAAgAGABgQAAICAgICAgICAgICAgICAgICAgICBgIwEAICAgIC", + "AgICAgICAgICAgICAgICAgICAgICAgICAgICAgoCVBACFAIYAloSAgIEAgQCBAACBAYABAgAAGgAFgIA", + "AAAELgIAAAAIXAIAAAAMGAYEAgAOEAoCAAAQEgYIBAASFAoEAAAUGAIAAAAWDAIAAAAWDgIAAAAYAgIA", + "AAAaHAwCAQAcHgoUAAAeMAwCAQAgIgoKAAAiJAYEAgAkJgoMAAAmKAwCAQAoMAIAAAAqLAoSAAAsMAwC", + "AQAuGgIAAAAuIAIAAAAuKgIAAAAwVgIAAAAyNBQOAAA0NgoGAAA2OAYEAhA4OgwCAQA6VAIAAAA8PhQM", + "AAA+QAoIAABAQgYEAg5CRAwCAQBEVAIAAABGSBQGAABISgoOAABKVAwCAQBMThQEAABOUAoQAABQVAwC", + "AQBSMgIAAABSPAIAAABSRgIAAABSTAIAAABUWgIAAABWUgIAAABWWAIAAABYBgIAAABaVgIAAABcXgYA", + "AABeCgIAAAAIFi5SVg==" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/referencetoatnlexer.rs b/runtime/Rust/tests/gen/referencetoatnlexer.rs index 1743a7501e..79bfaf4268 100644 --- a/runtime/Rust/tests/gen/referencetoatnlexer.rs +++ b/runtime/Rust/tests/gen/referencetoatnlexer.rs @@ -109,16 +109,10 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 0, 3, 21, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 1, 0, 4, 0, - 9, 8, 0, 11, 0, 12, 0, 10, 1, 1, 4, 1, 14, 8, 1, 11, 1, 12, 1, 15, 1, - 2, 1, 2, 1, 2, 1, 2, 0, 0, 3, 1, 1, 3, 2, 5, 3, 1, 0, 1, 2, 0, 10, 10, - 32, 32, 22, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 1, - 8, 1, 0, 0, 0, 3, 13, 1, 0, 0, 0, 5, 17, 1, 0, 0, 0, 7, 9, 2, 97, 122, - 0, 8, 7, 1, 0, 0, 0, 9, 10, 1, 0, 0, 0, 10, 8, 1, 0, 0, 0, 10, 11, 1, - 0, 0, 0, 11, 2, 1, 0, 0, 0, 12, 14, 2, 48, 57, 0, 13, 12, 1, 0, 0, 0, - 14, 15, 1, 0, 0, 0, 15, 13, 1, 0, 0, 0, 15, 16, 1, 0, 0, 0, 16, 4, 1, - 0, 0, 0, 17, 18, 7, 0, 0, 0, 18, 19, 1, 0, 0, 0, 19, 20, 6, 2, 0, 0, - 20, 6, 1, 0, 0, 0, 3, 0, 10, 15, 1, 6, 0, 0 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 4] = [ + "CAAGKgwBBAAOAAQCDgIEBA4EAgAIABIQABYAGAAUAgIIAhwQAhYCGAIeAgQCBAIEAgQAAAYCAgYECgYC", + "AAIEABQUQEAsAAICAAAAAAYCAAAAAAoCAAAAAhACAAAABhoCAAAACiICAAAADhIEwgH0AQAQDgIAAAAS", + "FAIAAAAUEAIAAAAUFgIAAAAWBAIAAAAYHARgcgAaGAIAAAAcHgIAAAAeGgIAAAAeIAIAAAAgCAIAAAAi", + "JA4AAAAkJgIAAAAmKAwEAAAoDAIAAAAGABQeAgwAAA==" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/referencetoatnparser.rs b/runtime/Rust/tests/gen/referencetoatnparser.rs index 302957991c..6390ba8d73 100644 --- a/runtime/Rust/tests/gen/referencetoatnparser.rs +++ b/runtime/Rust/tests/gen/referencetoatnparser.rs @@ -331,12 +331,9 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 1, 3, 14, 2, 0, 7, 0, 1, 0, 5, 0, 4, 8, 0, 10, 0, 12, 0, 7, 9, 0, - 1, 0, 3, 0, 10, 8, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 2, - 14, 0, 5, 1, 0, 0, 0, 2, 4, 7, 0, 0, 0, 3, 2, 1, 0, 0, 0, 4, 7, 1, 0, - 0, 0, 5, 3, 1, 0, 0, 0, 5, 6, 1, 0, 0, 0, 6, 9, 1, 0, 0, 0, 7, 5, 1, - 0, 0, 0, 8, 10, 5, 2, 0, 0, 9, 8, 1, 0, 0, 0, 9, 10, 1, 0, 0, 0, 10, - 11, 1, 0, 0, 0, 11, 12, 6, 0, -1, 0, 12, 1, 1, 0, 0, 0, 2, 5, 9 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 3] = [ + "CAIGHAQADgACAAoACBAAFAAYAA4SAAIABgAUEAACAAIAAgAAAAIAAAICAAIEHAAKAgAAAAQIDgAAAAYE", + "AgAAAAgOAgAAAAoGAgAAAAoMAgAAAAwSAgAAAA4KAgAAABAUCgQAABIQAgAAABIUAgAAABQWAgAAABYY", + "DAABABgCAgAAAAQKEg==" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/simplelrlexer.rs b/runtime/Rust/tests/gen/simplelrlexer.rs index 4027fa78f6..3a3a3b0c65 100644 --- a/runtime/Rust/tests/gen/simplelrlexer.rs +++ b/runtime/Rust/tests/gen/simplelrlexer.rs @@ -108,13 +108,9 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 0, 2, 14, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 1, 0, 4, 0, 7, 8, 0, 11, - 0, 12, 0, 8, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 1, 1, 3, 2, 1, 0, 1, 2, - 0, 10, 10, 32, 32, 14, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 1, 6, 1, - 0, 0, 0, 3, 10, 1, 0, 0, 0, 5, 7, 2, 97, 122, 0, 6, 5, 1, 0, 0, 0, 7, - 8, 1, 0, 0, 0, 8, 6, 1, 0, 0, 0, 8, 9, 1, 0, 0, 0, 9, 2, 1, 0, 0, 0, - 10, 11, 7, 0, 0, 0, 11, 12, 1, 0, 0, 0, 12, 13, 6, 1, 0, 0, 13, 4, 1, - 0, 0, 0, 2, 0, 8, 1, 6, 0, 0 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 3] = [ + "CAAEHAwBBAAOAAQCDgICAAgADhAAFgAYABACAgICAgICAgAABAICBgQCAAIEABQUQEAcAAICAAAAAAYC", + "AAAAAgwCAAAABhQCAAAACg4EwgH0AQAMCgIAAAAOEAIAAAAQDAIAAAAQEgIAAAASBAIAAAAUFg4AAAAW", + "GAIAAAAYGgwCAAAaCAIAAAAEABACDAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/simplelrparser.rs b/runtime/Rust/tests/gen/simplelrparser.rs index 220447cf13..93a07a54df 100644 --- a/runtime/Rust/tests/gen/simplelrparser.rs +++ b/runtime/Rust/tests/gen/simplelrparser.rs @@ -446,13 +446,9 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 1, 2, 17, 2, 0, 7, 0, 2, 1, 7, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 5, 1, 12, 8, 1, 10, 1, 12, 1, 15, 9, 1, 1, 1, 0, 1, 2, 2, 0, - 2, 0, 0, 15, 0, 4, 1, 0, 0, 0, 2, 6, 1, 0, 0, 0, 4, 5, 3, 2, 1, 0, 5, - 1, 1, 0, 0, 0, 6, 7, 6, 1, -1, 0, 7, 8, 5, 1, 0, 0, 8, 13, 1, 0, 0, - 0, 9, 10, 10, 2, 0, 0, 10, 12, 5, 1, 0, 0, 11, 9, 1, 0, 0, 0, 12, 15, - 1, 0, 0, 0, 13, 11, 1, 0, 0, 0, 13, 14, 1, 0, 0, 0, 14, 3, 1, 0, 0, - 0, 15, 13, 1, 0, 0, 0, 1, 13 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 3] = [ + "CAIEIgQADgAEAg4CAgACAAICAgICAgICAgIKAhgQAhQCGAIeEgICAgACBAQABAAAHgAIAgAAAAQMAgAA", + "AAgKBgQCAAoCAgAAAAwODAIBAA4QCgIAABAaAgAAABIUFAQAABQYCgIAABYSAgAAABgeAgAAABoWAgAA", + "ABocAgAAABwGAgAAAB4aAgAAAAIa" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/staticdfabaselistener.rs b/runtime/Rust/tests/gen/staticdfabaselistener.rs new file mode 100644 index 0000000000..51cbe4144d --- /dev/null +++ b/runtime/Rust/tests/gen/staticdfabaselistener.rs @@ -0,0 +1,143 @@ +// Generated from StaticDFA.g4 by ANTLR 4.13.2 + +use super::staticdfaparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by StaticDFAParser. + +pub trait StaticDFABaseListener<'arena>: + ParseTreeListener<'arena, StaticDFAParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_createtable(&mut self, _ctx: &CreateTableContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_createtable(&mut self, _ctx: &CreateTableContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_createview(&mut self, _ctx: &CreateViewContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_createview(&mut self, _ctx: &CreateViewContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_droptable(&mut self, _ctx: &DropTableContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_droptable(&mut self, _ctx: &DropTableContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_call(&mut self, _ctx: &CallContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_call(&mut self, _ctx: &CallContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_ref(&mut self, _ctx: &RefContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_ref(&mut self, _ctx: &RefContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_name(&mut self, _ctx: &NameContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_name(&mut self, _ctx: &NameContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_starloop(&mut self, _ctx: &StarLoopContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_starloop(&mut self, _ctx: &StarLoopContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_plusloop(&mut self, _ctx: &PlusLoopContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_plusloop(&mut self, _ctx: &PlusLoopContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_opt(&mut self, _ctx: &OptContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_opt(&mut self, _ctx: &OptContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_dupfirst(&mut self, _ctx: &DupFirstContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_dupfirst(&mut self, _ctx: &DupFirstContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_dupsecond(&mut self, _ctx: &DupSecondContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link StaticDFABaseParser#s}. + * @param ctx the parse tree + */ + fn exit_dupsecond(&mut self, _ctx: &DupSecondContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/staticdfalexer.rs b/runtime/Rust/tests/gen/staticdfalexer.rs new file mode 100644 index 0000000000..1392ae5796 --- /dev/null +++ b/runtime/Rust/tests/gen/staticdfalexer.rs @@ -0,0 +1,143 @@ +// Generated from StaticDFA.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const T__8:i32=9; +pub const T__9:i32=10; +pub const T__10:i32=11; +pub const T__11:i32=12; +pub const ID:i32=13; +pub const WS:i32=14; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;14] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "ID", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;13] = [ + None, Some("'create'"), Some("'table'"), Some("'view'"), Some("'drop'"), + Some("'('"), Some("')'"), Some("'.'"), Some("'a'"), Some("'b'"), Some("'c'"), + Some("'d'"), Some("'e'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;15] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, Some("ID"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, StaticDFALexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct StaticDFALexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { StaticDFALexer } +dbt_antlr4::impl_deref! { lexer => StaticDFALexer } + +impl<'input, 'arena, Input, TF> StaticDFALexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = StaticDFALexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct StaticDFALexerActions { +} + +impl StaticDFALexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for StaticDFALexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for StaticDFALexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "StaticDFALexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 13] = [ + "CAAcoAEMAQQADgAEAg4CBAQOBAQGDgYECA4IBAoOCgQMDgwEDg4OBBAOEAQSDhIEFA4UBBYOFgQYDhgE", + "Gg4aAgACAAIAAgACAAIAAgACAgICAgICAgICAgICBAIEAgQCBAIEAgYCBgIGAgYCBgIIAggCCgIKAgwC", + "DAIOAg4CEAIQAhICEgIUAhQCFgIWAhgIGIwBEBgWGBgYjgECGggalgEQGhYaGBqYAQIaAhoAABwCAgYE", + "CgYOCBIKFgwaDh4QIhImFCoWLhgyGjYcAgAEAgDCAfQBBgASFBoaQECiAQACAgAAAAAGAgAAAAAKAgAA", + "AAAOAgAAAAASAgAAAAAWAgAAAAAaAgAAAAAeAgAAAAAiAgAAAAAmAgAAAAAqAgAAAAAuAgAAAAAyAgAA", + "AAA2AgAAAAI6AgAAAAZIAgAAAApUAgAAAA5eAgAAABJoAgAAABZsAgAAABpwAgAAAB50AgAAACJ4AgAA", + "ACZ8AgAAACqAAQIAAAAuhAECAAAAMooBAgAAADaUAQIAAAA6PArGAQAAPD4K5AEAAD5ACsoBAABAQgrC", + "AQAAQkQK6AEAAERGCsoBAABGBAIAAABISgroAQAASkwKwgEAAExOCsQBAABOUArYAQAAUFIKygEAAFII", + "AgAAAFRWCuwBAABWWArSAQAAWFoKygEAAFpcCu4BAABcDAIAAABeYArIAQAAYGIK5AEAAGJkCt4BAABk", + "ZgrgAQAAZhACAAAAaGoKUAAAahQCAAAAbG4KUgAAbhgCAAAAcHIKXAAAchwCAAAAdHYKwgEAAHYgAgAA", + "AHh6CsQBAAB6JAIAAAB8fgrGAQAAfigCAAAAgAGCAQrIAQAAggEsAgAAAIQBhgEKygEAAIYBMAIAAACI", + "AYwBDgAAAIoBiAECAAAAjAGOAQIAAACOAYoBAgAAAI4BkAECAAAAkAE0AgAAAJIBlgEOAgAAlAGSAQIA", + "AACWAZgBAgAAAJgBlAECAAAAmAGaAQIAAACaAZwBAgAAAJwBngEMGgAAngE4AgAAAAYAjgGYAQIMAAA=" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/staticdfalistener.rs b/runtime/Rust/tests/gen/staticdfalistener.rs new file mode 100644 index 0000000000..07769495c8 --- /dev/null +++ b/runtime/Rust/tests/gen/staticdfalistener.rs @@ -0,0 +1,114 @@ +#![allow(nonstandard_style)] +// Generated from StaticDFA.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::staticdfaparser::*; + +pub trait StaticDFAListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, StaticDFAParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by the {@code createTable} + /// labeled alternative in {@link StaticDFAParser#stat}. + /// @param ctx the parse tree + fn enter_createTable<'input: 'arena>(&mut self, _ctx: &CreateTableContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code createTable} + /// labeled alternative in {@link StaticDFAParser#stat}. + /// @param ctx the parse tree + fn exit_createTable<'input: 'arena>(&mut self, _ctx: &CreateTableContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code createView} + /// labeled alternative in {@link StaticDFAParser#stat}. + /// @param ctx the parse tree + fn enter_createView<'input: 'arena>(&mut self, _ctx: &CreateViewContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code createView} + /// labeled alternative in {@link StaticDFAParser#stat}. + /// @param ctx the parse tree + fn exit_createView<'input: 'arena>(&mut self, _ctx: &CreateViewContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code dropTable} + /// labeled alternative in {@link StaticDFAParser#stat}. + /// @param ctx the parse tree + fn enter_dropTable<'input: 'arena>(&mut self, _ctx: &DropTableContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code dropTable} + /// labeled alternative in {@link StaticDFAParser#stat}. + /// @param ctx the parse tree + fn exit_dropTable<'input: 'arena>(&mut self, _ctx: &DropTableContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code call} + /// labeled alternative in {@link StaticDFAParser#expr}. + /// @param ctx the parse tree + fn enter_call<'input: 'arena>(&mut self, _ctx: &CallContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code call} + /// labeled alternative in {@link StaticDFAParser#expr}. + /// @param ctx the parse tree + fn exit_call<'input: 'arena>(&mut self, _ctx: &CallContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code ref} + /// labeled alternative in {@link StaticDFAParser#expr}. + /// @param ctx the parse tree + fn enter_ref<'input: 'arena>(&mut self, _ctx: &RefContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code ref} + /// labeled alternative in {@link StaticDFAParser#expr}. + /// @param ctx the parse tree + fn exit_ref<'input: 'arena>(&mut self, _ctx: &RefContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link StaticDFAParser#name}. + /// @param ctx the parse tree + fn enter_name<'input: 'arena>(&mut self, _ctx: &NameContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link StaticDFAParser#name}. + /// @param ctx the parse tree + fn exit_name<'input: 'arena>(&mut self, _ctx: &NameContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link StaticDFAParser#starLoop}. + /// @param ctx the parse tree + fn enter_starLoop<'input: 'arena>(&mut self, _ctx: &StarLoopContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link StaticDFAParser#starLoop}. + /// @param ctx the parse tree + fn exit_starLoop<'input: 'arena>(&mut self, _ctx: &StarLoopContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link StaticDFAParser#plusLoop}. + /// @param ctx the parse tree + fn enter_plusLoop<'input: 'arena>(&mut self, _ctx: &PlusLoopContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link StaticDFAParser#plusLoop}. + /// @param ctx the parse tree + fn exit_plusLoop<'input: 'arena>(&mut self, _ctx: &PlusLoopContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link StaticDFAParser#opt}. + /// @param ctx the parse tree + fn enter_opt<'input: 'arena>(&mut self, _ctx: &OptContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link StaticDFAParser#opt}. + /// @param ctx the parse tree + fn exit_opt<'input: 'arena>(&mut self, _ctx: &OptContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code dupFirst} + /// labeled alternative in {@link StaticDFAParser#dup}. + /// @param ctx the parse tree + fn enter_dupFirst<'input: 'arena>(&mut self, _ctx: &DupFirstContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code dupFirst} + /// labeled alternative in {@link StaticDFAParser#dup}. + /// @param ctx the parse tree + fn exit_dupFirst<'input: 'arena>(&mut self, _ctx: &DupFirstContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code dupSecond} + /// labeled alternative in {@link StaticDFAParser#dup}. + /// @param ctx the parse tree + fn enter_dupSecond<'input: 'arena>(&mut self, _ctx: &DupSecondContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code dupSecond} + /// labeled alternative in {@link StaticDFAParser#dup}. + /// @param ctx the parse tree + fn exit_dupSecond<'input: 'arena>(&mut self, _ctx: &DupSecondContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs new file mode 100644 index 0000000000..6075f49909 --- /dev/null +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -0,0 +1,1833 @@ +// Generated from StaticDFA.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::staticdfalistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const StaticDFA_T__0:i32=1; +pub const StaticDFA_T__1:i32=2; +pub const StaticDFA_T__2:i32=3; +pub const StaticDFA_T__3:i32=4; +pub const StaticDFA_T__4:i32=5; +pub const StaticDFA_T__5:i32=6; +pub const StaticDFA_T__6:i32=7; +pub const StaticDFA_T__7:i32=8; +pub const StaticDFA_T__8:i32=9; +pub const StaticDFA_T__9:i32=10; +pub const StaticDFA_T__10:i32=11; +pub const StaticDFA_T__11:i32=12; +pub const StaticDFA_ID:i32=13; +pub const StaticDFA_WS:i32=14; +pub const StaticDFA_EOF:i32=EOF; +pub const RULE_stat:usize = 0; +pub const RULE_expr:usize = 1; +pub const RULE_name:usize = 2; +pub const RULE_starLoop:usize = 3; +pub const RULE_plusLoop:usize = 4; +pub const RULE_opt:usize = 5; +pub const RULE_dup:usize = 6; +pub const ruleNames: [&'static str; 7] = [ + "stat", "expr", "name", "starLoop", "plusLoop", "opt", "dup" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;13] = [ + None, Some("'create'"), Some("'table'"), Some("'view'"), Some("'drop'"), + Some("'('"), Some("')'"), Some("'.'"), Some("'a'"), Some("'b'"), Some("'c'"), + Some("'d'"), Some("'e'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;15] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, Some("ID"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, StaticDFAParserExt<'input, 'arena>, StaticDFAParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + StaticDFAParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: StaticDFAListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct StaticDFATreeWalker; +impl StaticDFATreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: StaticDFAListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, StaticDFAParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum StaticDFAParserNodeKind { + StatContext, + ExprContext, + NameContext, + StarLoopContext, + PlusLoopContext, + OptContext, + DupContext, + Terminal, + Error, +} +pub type StaticDFAParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, StaticDFAParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => StaticDFAParser } +dbt_antlr4::impl_node_kind! { StaticDFAParserNodeKind { + StatContext(StatContextAll), ExprContext(ExprContextAll), DupContext(DupContextAll), ; NameContext(enter_name, exit_name, ), StarLoopContext(enter_starLoop, exit_starLoop, ), PlusLoopContext(enter_plusLoop, exit_plusLoop, ), OptContext(enter_opt, exit_opt, ), + }; listener = dyn StaticDFAListener<'arena, Tok>, +} + +pub struct StaticDFAParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> StaticDFAParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for StaticDFAParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for StaticDFAParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "StaticDFA.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } +} +//------------------- stat ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum StatContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + CreateTableContext(CreateTableContext<'input, 'arena, Tok>), + CreateViewContext(CreateViewContext<'input, 'arena, Tok>), + DropTableContext(DropTableContext<'input, 'arena, Tok>), + Error(StatContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { StatContextAll { } { CreateTableContext, CreateViewContext, DropTableContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { StatContextAll { } { CreateTableContext, CreateViewContext, DropTableContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { StaticDFAParserNodeKind::StatContextAll { CreateTableContext, CreateViewContext, DropTableContext, Error, } } +dbt_antlr4::impl_node_inner! { StaticDFAParserNodeKind::StatContext::StatContextAll { CreateTableContext, CreateViewContext, DropTableContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { StaticDFAListener::StaticDFAParserNodeKind::StatContextAll { CreateTableContext(enter_createTable, exit_createTable), CreateViewContext(enter_createView, exit_createView), DropTableContext(enter_dropTable, exit_dropTable), } } + +impl<'input, 'arena, Tok> Deref for StatContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn StatContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use StatContextAll::*; + match self{ + CreateTableContext(inner) => inner, + CreateViewContext(inner) => inner, + DropTableContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type StatContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, StatContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; +#[derive(Debug)] +pub struct StatContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for StatContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StatContext } + fn get_rule_index(&self) -> usize { RULE_stat } + fn make_node( + arena: &'arena Arena, + ctx: StatContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StatContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a StatContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => StatContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut StatContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut StatContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> StatContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, StatContextExt { + ph: PhantomData + } + ) + } +} + +pub trait StatContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> StatContextAttrs<'input, 'arena, Tok> for StatContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type CreateTableContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, CreateTableContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; + +pub trait CreateTableContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CreateTableContextAttrs<'input, 'arena, Tok> for CreateTableContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == StaticDFA_ID) + } +} +#[derive(Debug)] +pub struct CreateTableContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: StatContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CreateTableContextExt<'input, 'arena, Tok> +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StatContext } + fn get_rule_index(&self) -> usize { RULE_stat } + fn make_node( + arena: &'arena Arena, + ctx: CreateTableContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StatContextAll::CreateTableContext(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a CreateTableContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => StatContextAll<'input, 'arena, Tok>) { + StatContextAll::CreateTableContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut CreateTableContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut StatContextAll<'input, 'arena, Tok>) { + StatContextAll::CreateTableContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> StatContextAttrs<'input, 'arena, Tok> for CreateTableContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CreateTableContextExt<'input, 'arena, Tok> { + fn new(base: StatContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut StaticDFAParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut StatContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + StatContextAll::CreateTableContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type CreateViewContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, CreateViewContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; + +pub trait CreateViewContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CreateViewContextAttrs<'input, 'arena, Tok> for CreateViewContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == StaticDFA_ID) + } +} +#[derive(Debug)] +pub struct CreateViewContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: StatContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CreateViewContextExt<'input, 'arena, Tok> +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StatContext } + fn get_rule_index(&self) -> usize { RULE_stat } + fn make_node( + arena: &'arena Arena, + ctx: CreateViewContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StatContextAll::CreateViewContext(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a CreateViewContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => StatContextAll<'input, 'arena, Tok>) { + StatContextAll::CreateViewContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut CreateViewContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut StatContextAll<'input, 'arena, Tok>) { + StatContextAll::CreateViewContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> StatContextAttrs<'input, 'arena, Tok> for CreateViewContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CreateViewContextExt<'input, 'arena, Tok> { + fn new(base: StatContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut StaticDFAParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut StatContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + StatContextAll::CreateViewContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type DropTableContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, DropTableContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; + +pub trait DropTableContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> DropTableContextAttrs<'input, 'arena, Tok> for DropTableContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == StaticDFA_ID) + } +} +#[derive(Debug)] +pub struct DropTableContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: StatContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for DropTableContextExt<'input, 'arena, Tok> +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StatContext } + fn get_rule_index(&self) -> usize { RULE_stat } + fn make_node( + arena: &'arena Arena, + ctx: DropTableContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StatContextAll::DropTableContext(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a DropTableContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => StatContextAll<'input, 'arena, Tok>) { + StatContextAll::DropTableContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut DropTableContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut StatContextAll<'input, 'arena, Tok>) { + StatContextAll::DropTableContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> StatContextAttrs<'input, 'arena, Tok> for DropTableContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> DropTableContextExt<'input, 'arena, Tok> { + fn new(base: StatContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut StaticDFAParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut StatContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + StatContextAll::DropTableContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn stat(&mut self,) -> Result<&'arena StatContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(StatContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_stat)?; + let _local_ctx_fn = |recog: &Self| -> &'arena StatContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(23); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.dfa_predict(0)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + CreateTableContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CreateTableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(14); + recog.base.match_token(StaticDFA_T__0,&mut recog.err_handler)?; + recog.base.set_state(15); + recog.base.match_token(StaticDFA_T__1,&mut recog.err_handler)?; + recog.base.set_state(16); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + CreateViewContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CreateViewContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(17); + recog.base.match_token(StaticDFA_T__0,&mut recog.err_handler)?; + recog.base.set_state(18); + recog.base.match_token(StaticDFA_T__2,&mut recog.err_handler)?; + recog.base.set_state(19); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; + } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + recog.base.with_mut_ctx(|ctx| { + DropTableContextExt::copy_from(ctx); + ctx.set_alt_number(3); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena DropTableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(20); + recog.base.match_token(StaticDFA_T__3,&mut recog.err_handler)?; + recog.base.set_state(21); + recog.base.match_token(StaticDFA_T__1,&mut recog.err_handler)?; + recog.base.set_state(22); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- expr ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum ExprContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + CallContext(CallContext<'input, 'arena, Tok>), + RefContext(RefContext<'input, 'arena, Tok>), + Error(ExprContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { ExprContextAll { } { CallContext, RefContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { ExprContextAll { } { CallContext, RefContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { StaticDFAParserNodeKind::ExprContextAll { CallContext, RefContext, Error, } } +dbt_antlr4::impl_node_inner! { StaticDFAParserNodeKind::ExprContext::ExprContextAll { CallContext, RefContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { StaticDFAListener::StaticDFAParserNodeKind::ExprContextAll { CallContext(enter_call, exit_call), RefContext(enter_ref, exit_ref), } } + +impl<'input, 'arena, Tok> Deref for ExprContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn ExprContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use ExprContextAll::*; + match self{ + CallContext(inner) => inner, + RefContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type ExprContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ExprContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ExprContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ExprContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: ExprContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ExprContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ExprContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ExprContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ExprContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ExprContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ExprContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> ExprContextAttrs<'input, 'arena, Tok> for ExprContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type CallContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, CallContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; + +pub trait CallContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn name(&self) -> Option<&'arena NameContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CallContextAttrs<'input, 'arena, Tok> for CallContext<'input, 'arena, Tok> +{ + fn name(&self) -> Option<&'arena NameContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct CallContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CallContextExt<'input, 'arena, Tok> +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: CallContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::CallContext(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a CallContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::CallContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut CallContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::CallContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for CallContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CallContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut StaticDFAParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::CallContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type RefContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, RefContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; + +pub trait RefContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn name(&self) -> Option<&'arena NameContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> RefContextAttrs<'input, 'arena, Tok> for RefContext<'input, 'arena, Tok> +{ + fn name(&self) -> Option<&'arena NameContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct RefContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for RefContextExt<'input, 'arena, Tok> +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: RefContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::RefContext(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a RefContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::RefContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut RefContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::RefContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for RefContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> RefContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut StaticDFAParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::RefContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn expr(&mut self,) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ExprContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.dfa_predict(1)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + CallContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CallContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + /*InvokeRule name*/ + recog.base.set_state(25); + recog.name()?; + recog.base.set_state(26); + recog.base.match_token(StaticDFA_T__4,&mut recog.err_handler)?; + recog.base.set_state(27); + recog.base.match_token(StaticDFA_T__5,&mut recog.err_handler)?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + RefContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena RefContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + /*InvokeRule name*/ + recog.base.set_state(29); + recog.name()?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- name ---------------- +pub type NameContextAll<'input, 'arena, Tok = CommonToken<'input>> = NameContext<'input, 'arena, Tok>; + +pub type NameContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NameContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; +#[derive(Debug)] +pub struct NameContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for NameContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::NameContext } + fn get_rule_index(&self) -> usize { RULE_name } + fn make_node( + arena: &'arena Arena, + ctx: NameContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NameContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => NameContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NameContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut NameContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NameContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, NameContextExt { + ph: PhantomData + } + ) + } +} + +pub trait NameContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves all `TerminalNode`s corresponding to token ID in current rule + fn ID_all(&self) -> Vec<&TerminalNode<'input, 'arena, Tok>>; + /// Retrieves 'i'th TerminalNode corresponding to token ID, starting from 0. + /// Returns `None` if number of children corresponding to token ID is less than or equal to `i`. + fn ID(&self, i: usize) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> NameContextAttrs<'input, 'arena, Tok> for NameContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves all `TerminalNode`s corresponding to token ID in current rule + fn ID_all(&self) -> Vec<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().filter(|child| child.symbol.get_token_type() == StaticDFA_ID).collect() + } + /// Retrieves 'i'th TerminalNode corresponding to token ID, starting from 0. + /// Returns `None` if number of children corresponding to token ID is less than or equal to `i`. + fn ID(&self, i: usize) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().filter(|child| child.symbol.get_token_type() == StaticDFA_ID).nth(i) + } +} + +impl<'input, 'arena, Input, TF> StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn name(&mut self,) -> Result<&'arena NameContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_name)?; + let _local_ctx_fn = |recog: &Self| -> &'arena NameContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; + recog.base.set_state(37); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==StaticDFA_T__6 { + { + { + recog.base.set_state(33); + recog.base.match_token(StaticDFA_T__6,&mut recog.err_handler)?; + recog.base.set_state(34); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; + } + } + recog.base.set_state(39); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + } + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- starLoop ---------------- +pub type StarLoopContextAll<'input, 'arena, Tok = CommonToken<'input>> = StarLoopContext<'input, 'arena, Tok>; + +pub type StarLoopContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, StarLoopContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; +#[derive(Debug)] +pub struct StarLoopContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for StarLoopContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StarLoopContext } + fn get_rule_index(&self) -> usize { RULE_starLoop } + fn make_node( + arena: &'arena Arena, + ctx: StarLoopContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a StarLoopContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => StarLoopContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut StarLoopContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut StarLoopContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> StarLoopContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, StarLoopContextExt { + ph: PhantomData + } + ) + } +} + +pub trait StarLoopContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> StarLoopContextAttrs<'input, 'arena, Tok> for StarLoopContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +impl<'input, 'arena, Input, TF> StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn starLoop(&mut self,) -> Result<&'arena StarLoopContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(StarLoopContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_starLoop)?; + let _local_ctx_fn = |recog: &Self| -> &'arena StarLoopContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(44); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.base.dfa_predict(3)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + { + { + recog.base.set_state(40); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(41); + recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; + } + } + } + recog.base.set_state(46); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.base.dfa_predict(3)?; + } + recog.base.set_state(47); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(48); + recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- plusLoop ---------------- +pub type PlusLoopContextAll<'input, 'arena, Tok = CommonToken<'input>> = PlusLoopContext<'input, 'arena, Tok>; + +pub type PlusLoopContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PlusLoopContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; +#[derive(Debug)] +pub struct PlusLoopContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PlusLoopContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::PlusLoopContext } + fn get_rule_index(&self) -> usize { RULE_plusLoop } + fn make_node( + arena: &'arena Arena, + ctx: PlusLoopContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PlusLoopContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PlusLoopContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PlusLoopContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PlusLoopContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PlusLoopContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, PlusLoopContextExt { + ph: PhantomData + } + ) + } +} + +pub trait PlusLoopContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> PlusLoopContextAttrs<'input, 'arena, Tok> for PlusLoopContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +impl<'input, 'arena, Input, TF> StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn plusLoop(&mut self,) -> Result<&'arena PlusLoopContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(PlusLoopContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_plusLoop)?; + let _local_ctx_fn = |recog: &Self| -> &'arena PlusLoopContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(52); + recog.err_handler.sync(&mut recog.base)?; + _alt = 1; + loop { + match _alt { + x if x == 1 => + { + { + recog.base.set_state(50); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(51); + recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; + } + } + + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + recog.base.set_state(54); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.base.dfa_predict(4)?; + if _alt==2 || _alt==INVALID_ALT { break } + } + recog.base.set_state(56); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(57); + recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- opt ---------------- +pub type OptContextAll<'input, 'arena, Tok = CommonToken<'input>> = OptContext<'input, 'arena, Tok>; + +pub type OptContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, OptContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; +#[derive(Debug)] +pub struct OptContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for OptContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::OptContext } + fn get_rule_index(&self) -> usize { RULE_opt } + fn make_node( + arena: &'arena Arena, + ctx: OptContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a OptContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => OptContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut OptContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut OptContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OptContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, OptContextExt { + ph: PhantomData + } + ) + } +} + +pub trait OptContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> OptContextAttrs<'input, 'arena, Tok> for OptContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +impl<'input, 'arena, Input, TF> StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn opt(&mut self,) -> Result<&'arena OptContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(OptContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 10, RULE_opt)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OptContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(61); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.dfa_predict(5)? { + x if x == 1 =>{ + { + recog.base.set_state(59); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(60); + recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; + } + } + + _ => {} + } + recog.base.set_state(63); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(64); + recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- dup ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum DupContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + DupFirstContext(DupFirstContext<'input, 'arena, Tok>), + DupSecondContext(DupSecondContext<'input, 'arena, Tok>), + Error(DupContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { DupContextAll { } { DupFirstContext, DupSecondContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { DupContextAll { } { DupFirstContext, DupSecondContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { StaticDFAParserNodeKind::DupContextAll { DupFirstContext, DupSecondContext, Error, } } +dbt_antlr4::impl_node_inner! { StaticDFAParserNodeKind::DupContext::DupContextAll { DupFirstContext, DupSecondContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { StaticDFAListener::StaticDFAParserNodeKind::DupContextAll { DupFirstContext(enter_dupFirst, exit_dupFirst), DupSecondContext(enter_dupSecond, exit_dupSecond), } } + +impl<'input, 'arena, Tok> Deref for DupContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn DupContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use DupContextAll::*; + match self{ + DupFirstContext(inner) => inner, + DupSecondContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type DupContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, DupContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; +#[derive(Debug)] +pub struct DupContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for DupContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::DupContext } + fn get_rule_index(&self) -> usize { RULE_dup } + fn make_node( + arena: &'arena Arena, + ctx: DupContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(DupContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a DupContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => DupContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut DupContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut DupContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> DupContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, DupContextExt { + ph: PhantomData + } + ) + } +} + +pub trait DupContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> DupContextAttrs<'input, 'arena, Tok> for DupContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type DupFirstContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, DupFirstContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; + +pub trait DupFirstContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> DupFirstContextAttrs<'input, 'arena, Tok> for DupFirstContext<'input, 'arena, Tok> +{ +} +#[derive(Debug)] +pub struct DupFirstContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: DupContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for DupFirstContextExt<'input, 'arena, Tok> +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::DupContext } + fn get_rule_index(&self) -> usize { RULE_dup } + fn make_node( + arena: &'arena Arena, + ctx: DupFirstContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(DupContextAll::DupFirstContext(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a DupFirstContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => DupContextAll<'input, 'arena, Tok>) { + DupContextAll::DupFirstContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut DupFirstContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut DupContextAll<'input, 'arena, Tok>) { + DupContextAll::DupFirstContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> DupContextAttrs<'input, 'arena, Tok> for DupFirstContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> DupFirstContextExt<'input, 'arena, Tok> { + fn new(base: DupContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut StaticDFAParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut DupContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + DupContextAll::DupFirstContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut DupContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type DupSecondContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, DupSecondContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; + +pub trait DupSecondContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> DupSecondContextAttrs<'input, 'arena, Tok> for DupSecondContext<'input, 'arena, Tok> +{ +} +#[derive(Debug)] +pub struct DupSecondContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: DupContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for DupSecondContextExt<'input, 'arena, Tok> +{ + type NodeKind = StaticDFAParserNodeKind; + fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::DupContext } + fn get_rule_index(&self) -> usize { RULE_dup } + fn make_node( + arena: &'arena Arena, + ctx: DupSecondContext<'input, 'arena, Tok>, + ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(DupContextAll::DupSecondContext(ctx)) + } + fn cast_from<'a>( + node: &'a StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a DupSecondContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => DupContextAll<'input, 'arena, Tok>) { + DupContextAll::DupSecondContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut DupSecondContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut DupContextAll<'input, 'arena, Tok>) { + DupContextAll::DupSecondContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> DupContextAttrs<'input, 'arena, Tok> for DupSecondContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> DupSecondContextExt<'input, 'arena, Tok> { + fn new(base: DupContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut StaticDFAParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut DupContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + DupContextAll::DupSecondContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut DupContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> StaticDFAParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn dup(&mut self,) -> Result<&'arena DupContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(DupContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 12, RULE_dup)?; + let _local_ctx_fn = |recog: &Self| -> &'arena DupContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(70); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.dfa_predict(6)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + DupFirstContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena DupFirstContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(66); + recog.base.match_token(StaticDFA_T__10,&mut recog.err_handler)?; + recog.base.set_state(67); + recog.base.match_token(StaticDFA_T__11,&mut recog.err_handler)?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + DupSecondContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena DupSecondContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(68); + recog.base.match_token(StaticDFA_T__10,&mut recog.err_handler)?; + recog.base.set_state(69); + recog.base.match_token(StaticDFA_T__11,&mut recog.err_handler)?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +// the serialized ATN is followed by 6 static SLL prediction tables (-Xstatic-dfa): +// decision 0: LL(k), k=2, 5 states +// decision 1: LL(*) cyclic, 5 states +// decision 3: LL(k), k=2, 4 states +// decision 4: LL(k), k=2, 4 states +// decision 5: LL(k), k=2, 4 states +// decision 6: LL(k), k=2, 3 states +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 13] = [ + "CAIckgEEAA4ABAIOAgQEDgQEBg4GBAgOCAQKDgoEDA4MAgACAAIAAgACAAIAAgACAAIABgAwEAACAgIC", + "AgICAgICBgI+EAICBAIEAgQKBEgQBBQEGAROEgQCBgIGCgZWEAYUBhgGXBIGAgYCBgIGAggCCAgIahAI", + "FggYCGwCCAIIAggCCgIKBgp8EAoCCgIKAgoCDAIMAgwCDAYMjgEQDAIMAAAOAAQIDBAUGAAAkgEALgIA", + "AAAEPAIAAAAIQAIAAAAMWAIAAAAQaAIAAAAUegIAAAAYjAECAAAAHB4KAgAAHiAKBAAAIDAKGgAAIiQK", + "AgAAJCYKBgAAJjAKGgAAKCoKCAAAKiwKBAAALDAKGgAALhwCAAAALiICAAAALigCAAAAMAICAAAAMjQG", + "CAQANDYKCgAANjgKDAAAOD4CAAAAOj4GCAQAPDICAAAAPDoCAAAAPgYCAAAAQEoKGgAAQkQKDgAAREgK", + "GgAARkICAAAASE4CAAAASkYCAAAASkwCAAAATAoCAAAATkoCAAAAUFIKEAAAUlYKEgAAVFACAAAAVlwC", + "AAAAWFQCAAAAWFoCAAAAWl4CAAAAXFgCAAAAXmAKEAAAYGIKFAAAYg4CAAAAZGYKEAAAZmoKEgAAaGQC", + "AAAAamwCAAAAbGgCAAAAbG4CAAAAbnACAAAAcHIKEAAAcnQKFAAAdBICAAAAdngKEAAAeHwKEgAAenYC", + "AAAAenwCAAAAfH4CAAAAfoABChAAAIABggEKFAAAggEWAgAAAIQBhgEKFgAAhgGOAQoYAACIAYoBChYA", + "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEEDA4AChgAAAYCBAAMGBgYGAIC", + "AggIBAQEBgYGCAIKHgAABAIAAAYYGBgeGhoCAQEECgoGDg4IGhoCBggSAAACBAAGEhISEBACEhIEFBQG", + "CAgSAAACBAAGEhISEBACEhIEFBQGCggSAAACBAAGEhISEBACEhIEFBQGDAYMAAACAAYMDBYWAhgYBA==" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/visitorbasiclexer.rs b/runtime/Rust/tests/gen/visitorbasiclexer.rs index 227147551e..3d4690465c 100644 --- a/runtime/Rust/tests/gen/visitorbasiclexer.rs +++ b/runtime/Rust/tests/gen/visitorbasiclexer.rs @@ -108,9 +108,7 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 0, 1, 5, 6, -1, 2, 0, 7, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 4, - 0, 1, 1, 0, 0, 0, 1, 3, 1, 0, 0, 0, 3, 4, 5, 65, 0, 0, 4, 2, 1, 0, 0, - 0, 1, 0, 0 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 1] = [ + "CAACCgwBBAAOAAIAAgAAAAICAgIAAAgAAgIAAAACBgIAAAAGCAqCAQAACAQCAAAAAgAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/visitorbasicparser.rs b/runtime/Rust/tests/gen/visitorbasicparser.rs index 5cda9c0b69..ccdc82f3bc 100644 --- a/runtime/Rust/tests/gen/visitorbasicparser.rs +++ b/runtime/Rust/tests/gen/visitorbasicparser.rs @@ -294,9 +294,7 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 1, 1, 6, 2, 0, 7, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4, - 0, 2, 1, 0, 0, 0, 2, 3, 5, 1, 0, 0, 3, 4, 5, 0, 0, 1, 4, 1, 1, 0, 0, - 0, 0 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 1] = [ + "CAICDAQADgACAAIAAgACAAAAAgAAAAgABAIAAAAEBgoCAAAGCAoAAAIIAgIAAAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/visitorcalclexer.rs b/runtime/Rust/tests/gen/visitorcalclexer.rs index b81c6d747b..f531e47aa5 100644 --- a/runtime/Rust/tests/gen/visitorcalclexer.rs +++ b/runtime/Rust/tests/gen/visitorcalclexer.rs @@ -114,21 +114,12 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 0, 6, 33, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, - 2, 4, 7, 4, 2, 5, 7, 5, 1, 0, 4, 0, 15, 8, 0, 11, 0, 12, 0, 16, 1, 1, - 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 4, 5, 28, 8, 5, 11, - 5, 12, 5, 29, 1, 5, 1, 5, 0, 0, 6, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, - 6, 1, 0, 2, 1, 0, 48, 57, 2, 0, 9, 9, 32, 32, 34, 0, 1, 1, 0, 0, 0, - 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, - 0, 0, 11, 1, 0, 0, 0, 1, 14, 1, 0, 0, 0, 3, 18, 1, 0, 0, 0, 5, 20, 1, - 0, 0, 0, 7, 22, 1, 0, 0, 0, 9, 24, 1, 0, 0, 0, 11, 27, 1, 0, 0, 0, 13, - 15, 7, 0, 0, 0, 14, 13, 1, 0, 0, 0, 15, 16, 1, 0, 0, 0, 16, 14, 1, 0, - 0, 0, 16, 17, 1, 0, 0, 0, 17, 2, 1, 0, 0, 0, 18, 19, 5, 42, 0, 0, 19, - 4, 1, 0, 0, 0, 20, 21, 5, 47, 0, 0, 21, 6, 1, 0, 0, 0, 22, 23, 5, 43, - 0, 0, 23, 8, 1, 0, 0, 0, 24, 25, 5, 45, 0, 0, 25, 10, 1, 0, 0, 0, 26, - 28, 7, 1, 0, 0, 27, 26, 1, 0, 0, 0, 28, 29, 1, 0, 0, 0, 29, 27, 1, 0, - 0, 0, 29, 30, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 32, 6, 5, 0, 0, 32, - 12, 1, 0, 0, 0, 3, 0, 16, 29, 1, 0, 1, 0 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 6] = [ + "CAAMQgwBBAAOAAQCDgIEBA4EBAYOBgQIDggECg4KAgAIAB4QABYAGAAgAgICAgIEAgQCBgIGAggCCAIK", + "CAo4EAoWChgKOgIKAgoAAAwCAgYECgYOCBIKFgwCAAQCAGByBAASEkBARAACAgAAAAAGAgAAAAAKAgAA", + "AAAOAgAAAAASAgAAAAAWAgAAAAIcAgAAAAYkAgAAAAooAgAAAA4sAgAAABIwAgAAABY2AgAAABoeDgAA", + "ABwaAgAAAB4gAgAAACAcAgAAACAiAgAAACIEAgAAACQmClQAACYIAgAAACgqCl4AACoMAgAAACwuClYA", + "AC4QAgAAADAyCloAADIUAgAAADQ4DgIAADY0AgAAADg6AgAAADo2AgAAADo8AgAAADw+AgAAAD5ADAoA", + "AEAYAgAAAAYAIDoCAAIA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/visitorcalcparser.rs b/runtime/Rust/tests/gen/visitorcalcparser.rs index 0121d4e854..50277b5853 100644 --- a/runtime/Rust/tests/gen/visitorcalcparser.rs +++ b/runtime/Rust/tests/gen/visitorcalcparser.rs @@ -860,16 +860,10 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 1, 6, 22, 2, 0, 7, 0, 2, 1, 7, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 17, 8, 1, 10, 1, 12, 1, - 20, 9, 1, 1, 1, 0, 1, 2, 2, 0, 2, 0, 2, 1, 0, 2, 3, 1, 0, 4, 5, 21, - 0, 4, 1, 0, 0, 0, 2, 7, 1, 0, 0, 0, 4, 5, 3, 2, 1, 0, 5, 6, 5, 0, 0, - 1, 6, 1, 1, 0, 0, 0, 7, 8, 6, 1, -1, 0, 8, 9, 5, 1, 0, 0, 9, 18, 1, - 0, 0, 0, 10, 11, 10, 2, 0, 0, 11, 12, 7, 0, 0, 0, 12, 17, 3, 2, 1, 3, - 13, 14, 10, 1, 0, 0, 14, 15, 7, 1, 0, 0, 15, 17, 3, 2, 1, 2, 16, 10, - 1, 0, 0, 0, 16, 13, 1, 0, 0, 0, 17, 20, 1, 0, 0, 0, 18, 16, 1, 0, 0, - 0, 18, 19, 1, 0, 0, 0, 19, 3, 1, 0, 0, 0, 20, 18, 1, 0, 0, 0, 2, 16, - 18 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 4] = [ + "CAIMLAQADgAEAg4CAgACAAIAAgICAgICAgICAgICAgICAgICCgIiEAIUAhgCKBICAgIAAgQEAAQABAIA", + "BAYCAAgKKgAIAgAAAAQOAgAAAAgKBgQCAAoMCgAAAgwCAgAAAA4QDAIBABASCgIAABIkAgAAABQWFAQA", + "ABYYDgAAABgiBgQCBhocFAIAABweDgIAAB4iBgQCBCAUAgAAACAaAgAAACIoAgAAACQgAgAAACQmAgAA", + "ACYGAgAAACgkAgAAAAQgJA==" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/xmllexer.rs b/runtime/Rust/tests/gen/xmllexer.rs index d545446b0b..39087100b8 100644 --- a/runtime/Rust/tests/gen/xmllexer.rs +++ b/runtime/Rust/tests/gen/xmllexer.rs @@ -168,113 +168,49 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock> = LazyLock::new(|| vec![ - 4, 0, 18, 230, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, - 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, - 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, - 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, - 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, - 23, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 58, 8, 0, 10, 0, 12, 0, - 61, 9, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 80, 8, 1, 10, 1, 12, - 1, 83, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 5, 2, 93, - 8, 2, 10, 2, 12, 2, 96, 9, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, - 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 4, 4, 110, 8, 4, 11, 4, 12, 4, 111, - 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 4, 4, 121, 8, 4, 11, 4, 12, - 4, 122, 1, 4, 1, 4, 3, 4, 127, 8, 4, 1, 5, 1, 5, 3, 5, 131, 8, 5, 1, - 5, 3, 5, 134, 8, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, - 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, - 8, 1, 8, 1, 8, 1, 9, 4, 9, 159, 8, 9, 11, 9, 12, 9, 160, 1, 10, 1, 10, - 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, - 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 182, 8, 15, - 10, 15, 12, 15, 185, 9, 15, 1, 15, 1, 15, 1, 15, 5, 15, 190, 8, 15, - 10, 15, 12, 15, 193, 9, 15, 1, 15, 3, 15, 196, 8, 15, 1, 16, 1, 16, - 5, 16, 200, 8, 16, 10, 16, 12, 16, 203, 9, 16, 1, 17, 1, 17, 1, 17, - 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 3, 20, - 217, 8, 20, 1, 21, 3, 21, 220, 8, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, - 22, 1, 23, 1, 23, 1, 23, 1, 23, 3, 59, 81, 94, 0, 24, 3, 1, 5, 2, 7, - 3, 9, 4, 11, 5, 13, 6, 15, 7, 17, 8, 19, 0, 21, 9, 23, 10, 25, 11, 27, - 12, 29, 13, 31, 14, 33, 15, 35, 16, 37, 17, 39, 0, 41, 0, 43, 0, 45, - 0, 47, 18, 49, 0, 3, 0, 1, 2, 9, 2, 0, 9, 9, 32, 32, 2, 0, 38, 38, 60, - 60, 2, 0, 34, 34, 60, 60, 2, 0, 39, 39, 60, 60, 3, 0, 9, 10, 13, 13, - 32, 32, 3, 0, 48, 57, 65, 70, 97, 102, 1, 0, 48, 57, 3, 0, 183, 183, - 768, 879, 8255, 8256, 8, 0, 58, 58, 65, 90, 97, 122, 8304, 8591, 11264, - 12271, 12289, 55295, 63744, 64975, 65008, 65533, 239, 0, 3, 1, 0, 0, - 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, - 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, - 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 1, 23, 1, 0, 0, 0, 1, 25, 1, 0, 0, 0, - 1, 27, 1, 0, 0, 0, 1, 29, 1, 0, 0, 0, 1, 31, 1, 0, 0, 0, 1, 33, 1, 0, - 0, 0, 1, 35, 1, 0, 0, 0, 1, 37, 1, 0, 0, 0, 2, 47, 1, 0, 0, 0, 2, 49, - 1, 0, 0, 0, 3, 51, 1, 0, 0, 0, 5, 68, 1, 0, 0, 0, 7, 88, 1, 0, 0, 0, - 9, 101, 1, 0, 0, 0, 11, 126, 1, 0, 0, 0, 13, 133, 1, 0, 0, 0, 15, 135, - 1, 0, 0, 0, 17, 139, 1, 0, 0, 0, 19, 149, 1, 0, 0, 0, 21, 158, 1, 0, - 0, 0, 23, 162, 1, 0, 0, 0, 25, 165, 1, 0, 0, 0, 27, 170, 1, 0, 0, 0, - 29, 175, 1, 0, 0, 0, 31, 177, 1, 0, 0, 0, 33, 195, 1, 0, 0, 0, 35, 197, - 1, 0, 0, 0, 37, 204, 1, 0, 0, 0, 39, 208, 1, 0, 0, 0, 41, 210, 1, 0, - 0, 0, 43, 216, 1, 0, 0, 0, 45, 219, 1, 0, 0, 0, 47, 221, 1, 0, 0, 0, - 49, 226, 1, 0, 0, 0, 51, 52, 5, 60, 0, 0, 52, 53, 5, 33, 0, 0, 53, 54, - 5, 45, 0, 0, 54, 55, 5, 45, 0, 0, 55, 59, 1, 0, 0, 0, 56, 58, 9, 0, - 0, 0, 57, 56, 1, 0, 0, 0, 58, 61, 1, 0, 0, 0, 59, 60, 1, 0, 0, 0, 59, - 57, 1, 0, 0, 0, 60, 62, 1, 0, 0, 0, 61, 59, 1, 0, 0, 0, 62, 63, 5, 45, - 0, 0, 63, 64, 5, 45, 0, 0, 64, 65, 5, 62, 0, 0, 65, 66, 1, 0, 0, 0, - 66, 67, 4, 0, 0, 0, 67, 4, 1, 0, 0, 0, 68, 69, 5, 60, 0, 0, 69, 70, - 5, 33, 0, 0, 70, 71, 5, 91, 0, 0, 71, 72, 5, 67, 0, 0, 72, 73, 5, 68, - 0, 0, 73, 74, 5, 65, 0, 0, 74, 75, 5, 84, 0, 0, 75, 76, 5, 65, 0, 0, - 76, 77, 5, 91, 0, 0, 77, 81, 1, 0, 0, 0, 78, 80, 9, 0, 0, 0, 79, 78, - 1, 0, 0, 0, 80, 83, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 81, 79, 1, 0, 0, - 0, 82, 84, 1, 0, 0, 0, 83, 81, 1, 0, 0, 0, 84, 85, 5, 93, 0, 0, 85, - 86, 5, 93, 0, 0, 86, 87, 5, 62, 0, 0, 87, 6, 1, 0, 0, 0, 88, 89, 5, - 60, 0, 0, 89, 90, 5, 33, 0, 0, 90, 94, 1, 0, 0, 0, 91, 93, 9, 0, 0, - 0, 92, 91, 1, 0, 0, 0, 93, 96, 1, 0, 0, 0, 94, 95, 1, 0, 0, 0, 94, 92, - 1, 0, 0, 0, 95, 97, 1, 0, 0, 0, 96, 94, 1, 0, 0, 0, 97, 98, 5, 62, 0, - 0, 98, 99, 1, 0, 0, 0, 99, 100, 6, 2, 0, 0, 100, 8, 1, 0, 0, 0, 101, - 102, 5, 38, 0, 0, 102, 103, 3, 35, 16, 0, 103, 104, 5, 59, 0, 0, 104, - 10, 1, 0, 0, 0, 105, 106, 5, 38, 0, 0, 106, 107, 5, 35, 0, 0, 107, 109, - 1, 0, 0, 0, 108, 110, 3, 41, 19, 0, 109, 108, 1, 0, 0, 0, 110, 111, - 1, 0, 0, 0, 111, 109, 1, 0, 0, 0, 111, 112, 1, 0, 0, 0, 112, 113, 1, - 0, 0, 0, 113, 114, 5, 59, 0, 0, 114, 127, 1, 0, 0, 0, 115, 116, 5, 38, - 0, 0, 116, 117, 5, 35, 0, 0, 117, 118, 5, 120, 0, 0, 118, 120, 1, 0, - 0, 0, 119, 121, 3, 39, 18, 0, 120, 119, 1, 0, 0, 0, 121, 122, 1, 0, - 0, 0, 122, 120, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 124, 1, 0, 0, - 0, 124, 125, 5, 59, 0, 0, 125, 127, 1, 0, 0, 0, 126, 105, 1, 0, 0, 0, - 126, 115, 1, 0, 0, 0, 127, 12, 1, 0, 0, 0, 128, 134, 7, 0, 0, 0, 129, - 131, 5, 13, 0, 0, 130, 129, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0, 131, 132, - 1, 0, 0, 0, 132, 134, 5, 10, 0, 0, 133, 128, 1, 0, 0, 0, 133, 130, 1, - 0, 0, 0, 134, 14, 1, 0, 0, 0, 135, 136, 5, 60, 0, 0, 136, 137, 1, 0, - 0, 0, 137, 138, 6, 6, 1, 0, 138, 16, 1, 0, 0, 0, 139, 140, 5, 60, 0, - 0, 140, 141, 5, 63, 0, 0, 141, 142, 5, 120, 0, 0, 142, 143, 5, 109, - 0, 0, 143, 144, 5, 108, 0, 0, 144, 145, 1, 0, 0, 0, 145, 146, 3, 37, - 17, 0, 146, 147, 1, 0, 0, 0, 147, 148, 6, 7, 1, 0, 148, 18, 1, 0, 0, - 0, 149, 150, 5, 60, 0, 0, 150, 151, 5, 63, 0, 0, 151, 152, 1, 0, 0, - 0, 152, 153, 3, 35, 16, 0, 153, 154, 1, 0, 0, 0, 154, 155, 6, 8, 2, - 0, 155, 156, 6, 8, 3, 0, 156, 20, 1, 0, 0, 0, 157, 159, 8, 1, 0, 0, - 158, 157, 1, 0, 0, 0, 159, 160, 1, 0, 0, 0, 160, 158, 1, 0, 0, 0, 160, - 161, 1, 0, 0, 0, 161, 22, 1, 0, 0, 0, 162, 163, 5, 62, 0, 0, 163, 164, - 6, 10, 4, 0, 164, 24, 1, 0, 0, 0, 165, 166, 5, 63, 0, 0, 166, 167, 5, - 62, 0, 0, 167, 168, 1, 0, 0, 0, 168, 169, 6, 11, 5, 0, 169, 26, 1, 0, - 0, 0, 170, 171, 5, 47, 0, 0, 171, 172, 5, 62, 0, 0, 172, 173, 1, 0, - 0, 0, 173, 174, 6, 12, 5, 0, 174, 28, 1, 0, 0, 0, 175, 176, 5, 47, 0, - 0, 176, 30, 1, 0, 0, 0, 177, 178, 5, 61, 0, 0, 178, 32, 1, 0, 0, 0, - 179, 183, 5, 34, 0, 0, 180, 182, 8, 2, 0, 0, 181, 180, 1, 0, 0, 0, 182, - 185, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 186, - 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 186, 196, 5, 34, 0, 0, 187, 191, 5, - 39, 0, 0, 188, 190, 8, 3, 0, 0, 189, 188, 1, 0, 0, 0, 190, 193, 1, 0, - 0, 0, 191, 189, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 194, 1, 0, 0, - 0, 193, 191, 1, 0, 0, 0, 194, 196, 5, 39, 0, 0, 195, 179, 1, 0, 0, 0, - 195, 187, 1, 0, 0, 0, 196, 34, 1, 0, 0, 0, 197, 201, 3, 45, 21, 0, 198, - 200, 3, 43, 20, 0, 199, 198, 1, 0, 0, 0, 200, 203, 1, 0, 0, 0, 201, - 199, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 36, 1, 0, 0, 0, 203, 201, - 1, 0, 0, 0, 204, 205, 7, 4, 0, 0, 205, 206, 1, 0, 0, 0, 206, 207, 6, - 17, 0, 0, 207, 38, 1, 0, 0, 0, 208, 209, 7, 5, 0, 0, 209, 40, 1, 0, - 0, 0, 210, 211, 7, 6, 0, 0, 211, 42, 1, 0, 0, 0, 212, 217, 3, 45, 21, - 0, 213, 217, 2, 45, 46, 0, 214, 217, 3, 41, 19, 0, 215, 217, 7, 7, 0, - 0, 216, 212, 1, 0, 0, 0, 216, 213, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, - 216, 215, 1, 0, 0, 0, 217, 44, 1, 0, 0, 0, 218, 220, 7, 8, 0, 0, 219, - 218, 1, 0, 0, 0, 220, 46, 1, 0, 0, 0, 221, 222, 5, 63, 0, 0, 222, 223, - 5, 62, 0, 0, 223, 224, 1, 0, 0, 0, 224, 225, 6, 22, 5, 0, 225, 48, 1, - 0, 0, 0, 226, 227, 9, 0, 0, 0, 227, 228, 1, 0, 0, 0, 228, 229, 6, 23, - 2, 0, 229, 50, 1, 0, 0, 0, 18, 0, 1, 2, 59, 81, 94, 111, 122, 126, 130, - 133, 160, 183, 191, 195, 201, 216, 219, 6, 6, 0, 0, 5, 1, 0, 3, 0, 0, - 5, 2, 0, 1, 10, 0, 4, 0, 0 -]); \ No newline at end of file + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 43] = [ + "CAAkzAMMAQwBDAEEAA4ABAIOAgQEDgQEBg4GBAgOCAQKDgoEDA4MBA4ODgQQDhAEEg4SBBQOFAQWDhYE", + "GA4YBBoOGgQcDhwEHg4eBCAOIAQiDiIEJA4kBCYOJgQoDigEKg4qBCwOLAQuDi4CAAIAAgACAAIAAgAK", + "AHQQABQAGAB6EgACAAIAAgACAAIAAgACAgICAgICAgICAgICAgICAgICAgICCgKgARACFAIYAqYBEgIC", + "AgICAgICAgIEAgQCBAIECgS6ARAEFAQYBMABEgQCBAIEAgQCBAIGAgYCBgIGAggCCAIIAggICNwBEAgW", + "CBgI3gECCAIIAggCCAIIAggCCAgI8gEQCBYIGAj0AQIIAggGCP4BEAgCCgIKBgqGAhAKAgoGCowCEAoC", + "DAIMAgwCDAIOAg4CDgIOAg4CDgIOAg4CDgIOAhACEAIQAhACEAIQAhACEAISCBK+AhASFhIYEsACAhQC", + "FAIUAhYCFgIWAhYCFgIYAhgCGAIYAhgCGgIaAhwCHAIeAh4KHuwCEB4UHhge8gISHgIeAh4CHgoe/AIQ", + "HhQeGB6CAxIeAh4GHogDEB4CIAIgCiCQAxAgFCAYIJYDEiACIgIiAiICIgIkAiQCJgImAigCKAIoAigG", + "KLIDECgCKgYquAMQKgIsAiwCLAIsAiwCLgIuAi4CLgZ2ogG8AQAwBgIKBA4GEggWChoMHg4iECYAKhIu", + "FDIWNhg6Gj4cQh5GIEoiTgBSAFYAWgBeJGIABgACBBIEABISQEAEAExMeHgEAEREeHgEAE5OeHgGABIU", + "GhpAQAYAYHKCAYwBwgHMAQIAYHIGAO4C7gKADN4N/oABgIEBEAB0dIIBtAHCAfQB4IEBnoYBgLAB3r8B", + "gsAB/t8GgOQHnvcH4PcH+v8H3gMABgIAAAAACgIAAAAADgIAAAAAEgIAAAAAFgIAAAAAGgIAAAAAHgIA", + "AAAAIgIAAAAAJgIAAAAAKgIAAAACLgIAAAACMgIAAAACNgIAAAACOgIAAAACPgIAAAACQgIAAAACRgIA", + "AAACSgIAAAAEXgIAAAAEYgIAAAAGZgIAAAAKiAECAAAADrABAgAAABLKAQIAAAAW/AECAAAAGooCAgAA", + "AB6OAgIAAAAilgICAAAAJqoCAgAAACq8AgIAAAAuxAICAAAAMsoCAgAAADbUAgIAAAA63gICAAAAPuIC", + "AgAAAEKGAwIAAABGigMCAAAASpgDAgAAAE6gAwIAAABSpAMCAAAAVrADAgAAAFq2AwIAAABeugMCAAAA", + "YsQDAgAAAGZoCngAAGhqCkIAAGpsCloAAGxuCloAAG52AgAAAHB0EgAAAHJwAgAAAHR6AgAAAHZ4AgAA", + "AHZyAgAAAHh8AgAAAHp2AgAAAHx+CloAAH6AAQpaAACAAYIBCnwAAIIBhAECAAAAhAGGAQgAAACGAQgC", + "AAAAiAGKAQp4AACKAYwBCkIAAIwBjgEKtgEAAI4BkAEKhgEAAJABkgEKiAEAAJIBlAEKggEAAJQBlgEK", + "qAEAAJYBmAEKggEAAJgBmgEKtgEAAJoBogECAAAAnAGgARIAAACeAZwBAgAAAKABpgECAAAAogGkAQIA", + "AACiAZ4BAgAAAKQBqAECAAAApgGiAQIAAACoAaoBCroBAACqAawBCroBAACsAa4BCnwAAK4BDAIAAACw", + "AbIBCngAALIBtAEKQgAAtAG8AQIAAAC2AboBEgAAALgBtgECAAAAugHAAQIAAAC8Ab4BAgAAALwBuAEC", + "AAAAvgHCAQIAAADAAbwBAgAAAMIBxAEKfAAAxAHGAQIAAADGAcgBDAQAAMgBEAIAAADKAcwBCkwAAMwB", + "zgEGRiAAzgHQAQp2AADQARQCAAAA0gHUAQpMAADUAdYBCkYAANYB2gECAAAA2AHcAQZSJgDaAdgBAgAA", + "ANwB3gECAAAA3gHaAQIAAADeAeABAgAAAOAB4gECAAAA4gHkAQp2AADkAf4BAgAAAOYB6AEKTAAA6AHq", + "AQpGAADqAewBCvABAADsAfABAgAAAO4B8gEGTiQA8AHuAQIAAADyAfQBAgAAAPQB8AECAAAA9AH2AQIA", + "AAD2AfgBAgAAAPgB+gEKdgAA+gH+AQIAAAD8AdIBAgAAAPwB5gECAAAA/gEYAgAAAIACjAIOAAAAggKG", + "AgoaAACEAoICAgAAAIQChgICAAAAhgKIAgIAAACIAowCChQAAIoCgAICAAAAigKEAgIAAACMAhwCAAAA", + "jgKQAgp4AACQApICAgAAAJIClAIMDAIAlAIgAgAAAJYCmAIKeAAAmAKaAgp+AACaApwCCvABAACcAp4C", + "CtoBAACeAqACCtgBAACgAqICAgAAAKICpAIGSiIApAKmAgIAAACmAqgCDA4CAKgCJAIAAACqAqwCCngA", + "AKwCrgIKfgAArgKwAgIAAACwArICBkYgALICtAICAAAAtAK2AgwQBAC2ArgCDBAGALgCKAIAAAC6Ar4C", + "EAIAALwCugICAAAAvgLAAgIAAADAArwCAgAAAMACwgICAAAAwgIsAgAAAMQCxgIKfAAAxgLIAgwUCADI", + "AjACAAAAygLMAgp+AADMAs4CCnwAAM4C0AICAAAA0ALSAgwWCgDSAjQCAAAA1ALWAgpeAADWAtgCCnwA", + "ANgC2gICAAAA2gLcAgwYCgDcAjgCAAAA3gLgAgpeAADgAjwCAAAA4gLkAgp6AADkAkACAAAA5gLuAgpE", + "AADoAuwCEAQAAOoC6AICAAAA7ALyAgIAAADuAuoCAgAAAO4C8AICAAAA8AL0AgIAAADyAu4CAgAAAPQC", + "iAMKRAAA9gL+AgpOAAD4AvwCEAYAAPoC+AICAAAA/AKCAwIAAAD+AvoCAgAAAP4CgAMCAAAAgAOEAwIA", + "AACCA/4CAgAAAIQDiAMKTgAAhgPmAgIAAACGA/YCAgAAAIgDRAIAAACKA5IDBloqAIwDkAMGVigAjgOM", + "AwIAAACQA5YDAgAAAJIDjgMCAAAAkgOUAwIAAACUA0gCAAAAlgOSAwIAAACYA5oDDggAAJoDnAMCAAAA", + "nAOeAwwiAACeA0wCAAAAoAOiAw4KAACiA1ACAAAApAOmAw4MAACmA1QCAAAAqAOyAwZaKgCqA7IDBFpc", + "AKwDsgMGUiYArgOyAw4OAACwA6gDAgAAALADqgMCAAAAsAOsAwIAAACwA64DAgAAALIDWAIAAAC0A7gD", + "DhAAALYDtAMCAAAAuANcAgAAALoDvAMKfgAAvAO+Awp8AAC+A8ADAgAAAMADwgMMLAoAwgNgAgAAAMQD", + "xgMSAAAAxgPIAwIAAADIA8oDDC4EAMoDZAIAAAAkAAIEdqIBvAHeAfQB/AGEAooCwALuAv4ChgOSA7AD", + "tgMMDAAACgIABgAACgQAAhQACAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/static_dfa_tests.rs b/runtime/Rust/tests/static_dfa_tests.rs new file mode 100644 index 0000000000..9f96b61a95 --- /dev/null +++ b/runtime/Rust/tests/static_dfa_tests.rs @@ -0,0 +1,166 @@ +//! Tests for table-driven static SLL prediction (`-Xstatic-dfa`). +//! +//! The parser in `gen/staticdfaparser.rs` is generated with `-Xstatic-dfa`; +//! every non-LL(1) decision in `grammars/StaticDFA.g4` is statically +//! decidable, so the generated code drives them all through +//! `BaseParser::dfa_predict` tables (LL(2) alt blocks, a cyclic LL(*) +//! dotted-name decision, non-LL(1) star/plus/optional decisions, and an +//! exact ambiguity resolved min-alt) with no `adaptive_predict` call sites. + +#[rustfmt::skip] +mod gen { + #![allow(non_snake_case)] + #![allow(clippy::all)] + pub mod staticdfalexer; + pub mod staticdfalistener; + pub mod staticdfaparser; +} + +use dbt_antlr4::common_token_stream::CommonTokenStream; +use dbt_antlr4::recognizer::Recognizer; +use dbt_antlr4::token_factory::CommonTokenFactory; +use dbt_antlr4::trees::string_tree; +use dbt_antlr4::{Arena, InputStream}; + +use crate::gen::staticdfalexer::StaticDFALexer; +use crate::gen::staticdfaparser::StaticDFAParser; + +fn parse(input: &'static str, rule: &str) -> Result { + Arena::with(|arena| { + let lexer = StaticDFALexer::<_, CommonTokenFactory>::new(arena, InputStream::new(input)); + let tokens = CommonTokenStream::new(lexer); + let mut parser = StaticDFAParser::new(arena, tokens); + match rule { + "stat" => parser + .stat() + .map(|ctx| string_tree(ctx, parser.get_rule_names())), + "expr" => parser + .expr() + .map(|ctx| string_tree(ctx, parser.get_rule_names())), + "starLoop" => parser + .starLoop() + .map(|ctx| string_tree(ctx, parser.get_rule_names())), + "plusLoop" => parser + .plusLoop() + .map(|ctx| string_tree(ctx, parser.get_rule_names())), + "opt" => parser + .opt() + .map(|ctx| string_tree(ctx, parser.get_rule_names())), + "dup" => parser + .dup() + .map(|ctx| string_tree(ctx, parser.get_rule_names())), + _ => unreachable!(), + } + }) +} + +/// LL(2)/LL(3) keyword-pair alt block. +#[test] +fn test_llk_alt_block() { + assert_eq!( + parse("create table foo", "stat").unwrap(), + "(stat create table foo)" + ); + assert_eq!( + parse("create view foo", "stat").unwrap(), + "(stat create view foo)" + ); + assert_eq!( + parse("drop table foo", "stat").unwrap(), + "(stat drop table foo)" + ); +} + +/// LL(*): the cyclic DFA scans an arbitrarily long dotted name; the token +/// after it ('(' vs EOF) picks the alternative. +#[test] +fn test_llstar_dotted_name() { + assert_eq!( + parse("aa.bb.cc.dd()", "expr").unwrap(), + "(expr (name aa . bb . cc . dd) ( ))" + ); + assert_eq!( + parse("aa.bb.cc.dd", "expr").unwrap(), + "(expr (name aa . bb . cc . dd))" + ); + // single component, both ways + assert_eq!(parse("aa()", "expr").unwrap(), "(expr (name aa) ( ))"); + assert_eq!(parse("aa", "expr").unwrap(), "(expr (name aa))"); +} + +/// Non-LL(1) star loop: enter/exit needs LA(2) ('a b' repeats vs final 'a c'). +#[test] +fn test_dfa_star_loop() { + assert_eq!(parse("a c", "starLoop").unwrap(), "(starLoop a c)"); + assert_eq!(parse("a b a c", "starLoop").unwrap(), "(starLoop a b a c)"); + assert_eq!( + parse("a b a b a c", "starLoop").unwrap(), + "(starLoop a b a b a c)" + ); +} + +/// Non-LL(1) plus loop: continue/exit needs LA(2). +#[test] +fn test_dfa_plus_loop() { + assert_eq!(parse("a b a c", "plusLoop").unwrap(), "(plusLoop a b a c)"); + assert_eq!( + parse("a b a b a c", "plusLoop").unwrap(), + "(plusLoop a b a b a c)" + ); +} + +/// Non-LL(1) optional: enter/bypass needs LA(2). +#[test] +fn test_dfa_optional() { + assert_eq!(parse("a c", "opt").unwrap(), "(opt a c)"); + assert_eq!(parse("a b a c", "opt").unwrap(), "(opt a b a c)"); +} + +/// Exact ambiguity: static min-alt resolution must pick alternative 1 +/// (#dupFirst), exactly like runtime SLL/LL prediction. +#[test] +fn test_exact_ambiguity_min_alt() { + use crate::gen::staticdfaparser::DupContextAll; + Arena::with(|arena| { + let lexer = StaticDFALexer::<_, CommonTokenFactory>::new(arena, InputStream::new("d e")); + let tokens = CommonTokenStream::new(lexer); + let mut parser = StaticDFAParser::new(arena, tokens); + let result = parser.dup().unwrap(); + assert!( + matches!(result, DupContextAll::DupFirstContext(_)), + "min-alt resolution must pick #dupFirst" + ); + }); +} + +/// Prediction failure surfaces as an error (recovered or not), never a panic +/// or infinite loop - including mid-scan failures of the cyclic LL(*) DFA. +#[test] +fn test_no_viable_alt_handling() { + // 'create foo' - fails inside the LL(2) DFA at depth 2 + let r = parse("create foo", "stat"); + match r { + Ok(tree) => assert!(tree.contains("create")), // recovered parse + Err(_) => {} // unrecoverable is fine too + } + // dotted name that ends at a dot: cyclic DFA hits EOF mid-scan + let r = parse("aa.bb.", "expr"); + match r { + Ok(tree) => assert!(tree.contains("aa")), + Err(_) => {} + } +} + +/// The generated parser must contain zero adaptive_predict call sites. +#[test] +fn test_no_adaptive_predict_in_generated_code() { + let src = include_str!("gen/staticdfaparser.rs"); + assert!( + !src.contains("adaptive_predict"), + "StaticDFA parser should be fully table-driven" + ); + assert!( + src.contains("dfa_predict"), + "expected static DFA call sites" + ); +} diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg index 7ba7a7eb6d..396f3485c2 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg @@ -236,7 +236,7 @@ fileHeader(grammarFileName, ANTLRVersion) ::= << // Generated from by ANTLR >> -Parser(parser, funcs, atn, sempredFuncs, superClass) ::= << +Parser(parser, funcs, atn, sempredFuncs, superClass, staticDFAs) ::= << @@ -260,7 +260,7 @@ abstract class DFA { } >> -Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass) ::= << +Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass, staticDFAs) ::= << @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"}) public class extends { static { RuntimeMetaData.checkVersion("", RuntimeMetaData.VERSION); } @@ -322,6 +322,10 @@ case : + + + + } >> @@ -643,6 +647,82 @@ case +1: } while ( _alt!= && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); >> +// Statically-precomputed SLL prediction (-Xstatic-dfa): same shapes as the +// adaptive blocks above, but the decision is driven by a precomputed table +// via Parser.dfaPredict instead of adaptivePredict. All tables are packed +// into one compact serialized blob deserialized at class initialization, in +// the same vein as _serializedATN. + +SerializedStaticDFAs(dfas) ::= << +// static SLL prediction tables: +}; separator="\n"> +private static final String[] _serializedStaticDFA = { + "}; separator=",\n"> +}; +private static final org.antlr.v4.runtime.atn.StaticDFATables _staticDFAs = + org.antlr.v4.runtime.atn.StaticDFATables.deserialize(_serializedStaticDFA); +>> + +staticDFAPredict(choice) ::= "dfaPredict(_staticDFAs, )" + +DFAAltBlock(choice, preamble, alts, error) ::= << +setState(); +_errHandler.sync(this); + = _input.LT(1); + +switch ( ) { +: + + break;}; separator="\n"> +} +>> + +DFAOptionalBlock(choice, alts, error) ::= << +setState(); +_errHandler.sync(this); +switch ( ) { +: + + break;}; separator="\n"> +} +>> + +DFAStarBlock(choice, alts, sync, iteration) ::= << +setState(); +_errHandler.sync(this); +_alt = ; +while ( _alt!= && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + + + } + setState(); + _errHandler.sync(this); + _alt = ; +} +>> + +DFAPlusBlock(choice, alts, error) ::= << +setState(); +_errHandler.sync(this); +_alt = 1; +do { + switch (_alt) { + : + + break;}; separator="\n"> + default: + + } + setState(); + _errHandler.sync(this); + _alt = ; +} while ( _alt!= && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); +>> + Sync(s) ::= "sync();" ThrowNoViableAlt(t) ::= "throw new NoViableAltException(this);" diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index d1c5e54966..755ba37540 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -248,7 +248,7 @@ fileHeader(grammarFileName, ANTLRVersion) ::= << // Generated from by ANTLR >> -Parser(parser, funcs, atn, sempredFuncs, superClass) ::= << +Parser(parser, funcs, atn, sempredFuncs, superClass, staticDFAs) ::= << dbt_antlr4::check_version!("2","0"); _:i32=;}; separator=" \n"> @@ -764,6 +764,76 @@ loop { } >> +// Statically-precomputed SLL prediction (-Xstatic-dfa): same shapes as the +// adaptive blocks above, but the decision is driven by a precomputed table +// via BaseParser::dfa_predict instead of adaptive_predict. The tables are +// carried inside the serialized ATN blob (see SerializedBase64ATN) and +// decoded together with the ATN into its static_dfas field. + +staticDFAPredict(choice) ::= ".base.dfa_predict()?" + +DFAAltBlock(choice, preamble, alts, error) ::= << +.base.set_state(); +.err_handler.sync(&mut .base)?; +.base.input.lt(1).map(|t| t as _);})> + +match { + =>{ + + \} + }; separator=",\n"> + _ => {} +} +>> + +DFAOptionalBlock(choice, alts, error) ::= << +.base.set_state(); +.err_handler.sync(&mut .base)?; +match { + =>{ + + \} + }; separator="\n"> + _ => {} +} +>> + +DFAStarBlock(choice, alts, sync, iteration) ::= << +.base.set_state(); +.err_handler.sync(&mut .base)?; +_alt = ; +while { _alt!= && _alt!=INVALID_ALT } { + if _alt==1 { + + + } + .base.set_state(); + .err_handler.sync(&mut .base)?; + _alt = ; +} +>> + +DFAPlusBlock(choice, alts, error) ::= << +.base.set_state(); +.err_handler.sync(&mut .base)?; +_alt = 1; +loop { + match _alt { + => + + }; separator=",\n"> + _ => Err()? + } + .base.set_state(); + .err_handler.sync(&mut .base)?; + _alt = ; + if _alt== || _alt==INVALID_ALT { break } +} +>> + Sync(s) ::= ".err_handler.sync()?;" ThrowNoViableAlt(t) ::= "ANTLRError::no_alt(&mut .base)" @@ -1361,13 +1431,17 @@ where >> -SerializedATN(model) ::= << +SerializedBase64ATN(model) ::= << + +// the serialized ATN is followed by static SLL prediction tables (-Xstatic-dfa): +}; separator="\n"> + static ATN_SIMULATOR_MANAGER: LazyLock\ = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock\ = - LazyLock::new(|| ATNDeserializer::new(None).deserialize(&mut _serializedATN.iter())); -static _serializedATN: LazyLock\\> = LazyLock::new(|| vec![ - -]); + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; ] = [ + "}; separator=",\n"> +]; >> /** Using a type to init value map, try to init a type; if not in table diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index 9af99573a9..0032923242 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -115,6 +115,7 @@ public Option(String fieldName, String name, OptionArgType argType, String descr public boolean longMessages = false; public boolean exact_output_dir = false; public boolean decision_report = false; + public boolean static_dfa = false; public final static Option[] optionDefs = { new Option("outputDirectory", "-o", OptionArgType.STRING, "specify output directory where all output is generated"), @@ -139,6 +140,7 @@ public Option(String fieldName, String name, OptionArgType argType, String descr new Option("log", "-Xlog", "dump lots of logging info to antlr-timestamp.log"), new Option("exact_output_dir", "-Xexact-output-dir", "all output goes into -o dir regardless of paths/package"), new Option("decision_report", "-Xdecision-report", "classify every parser decision by required static lookahead (LL(1)/LL(k)/LL(*)/ambiguous/context-sensitive) and print a report"), + new Option("static_dfa", "-Xstatic-dfa", "precompute SLL prediction DFAs and generate table-driven prediction instead of adaptivePredict where provably behavior-preserving (Java/Rust targets)"), }; // helper vars for option management @@ -413,6 +415,11 @@ public void processNonCombinedGrammar(Grammar g, boolean gencode) { System.out.print(DecisionClassifier.report(g)); } + // PRECOMPUTE STATIC SLL PREDICTION TABLES FOR SAFE NON-LL(1) DECISIONS + if ( static_dfa && !force_atn && !g.isLexer() && g.atn!=null ) { + g.staticDecisionDFAs = DecisionClassifier.buildTables(g); + } + // GENERATE CODE if ( gencode ) { CodeGenPipeline gen = new CodeGenPipeline(g, codeGenerator); diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 77bc8fc01b..39d5f921e5 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -129,6 +129,12 @@ public static class Result { public final List contextSensitiveConflicts = new ArrayList(); /** Conflicts involving widening-tainted configs: possibly analysis artifacts; untrusted. */ public final List approxConflicts = new ArrayList(); + /** + * The serialized prediction table, populated only when the decision + * is statically decidable with behavior preservation (category LLK, + * LLSTAR, or trusted EXACT_AMBIG). + */ + public StaticDFA dfa; public Result(DecisionState decisionState) { this.decisionState = decisionState; @@ -190,6 +196,15 @@ public Result(DecisionState decisionState) { /** Wall-clock budget per construction attempt; exceeding it counts as overflow. */ public long attemptBudgetMs = 5000; + /** + * When set (table-building mode), abandon a decision as soon as an + * untrusted (tainted or non-exact) conflict is found: no widening level + * can make such a decision table-eligible, so there is no point burning + * the state/time budget on it. Leave false for classification reports, + * where complete conflict inventories are wanted. + */ + public boolean abortOnUntrustedConflict = false; + protected final Grammar g; protected final ATN atn; protected final IntervalSet allTokens; @@ -270,7 +285,8 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { Map, Integer> stateIds = new HashMap, Integer>(); List> states = new ArrayList>(); List> edges = new ArrayList>(); - List terminal = new ArrayList(); // accept or conflict; no expansion + List> edgeLabels = new ArrayList>(); + List acceptAlts = new ArrayList(); // 0 = not an accept state Set start = new LinkedHashSet(); Set startBusy = new HashSet(); @@ -282,7 +298,8 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { stateIds.put(start, 0); states.add(start); edges.add(new ArrayList()); - terminal.add(Boolean.FALSE); + edgeLabels.add(new ArrayList()); + acceptAlts.add(0); Deque work = new ArrayDeque(); work.add(0); @@ -297,11 +314,11 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { BitSet alts = PredictionMode.getAlts(cs); if (alts.cardinality() <= 1) { - terminal.set(d, Boolean.TRUE); // accept (or dead) state + // accept (or, for cardinality 0, dead/error) state + acceptAlts.set(d, Math.max(0, alts.nextSetBit(0))); continue; } if (PredictionMode.hasSLLConflictTerminatingPrediction(PredictionMode.SLL, cs)) { - terminal.set(d, Boolean.TRUE); Collection altSubsets = PredictionMode.getConflictingAltSubsets(cs); boolean exact = PredictionMode.allSubsetsConflict(altSubsets) && PredictionMode.allSubsetsEqual(altSubsets); @@ -313,21 +330,34 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { if (tainted) res.approxConflicts.add(conflicting); else if (exact) res.exactAmbigConflicts.add(conflicting); else res.contextSensitiveConflicts.add(conflicting); + if (!tainted && exact) { + // trusted exact ambiguity: min-alt resolution matches + // both runtime SLL and full-context LL + acceptAlts.set(d, conflicting.nextSetBit(0)); + } + else if (abortOnUntrustedConflict) { + // no widening level can make this decision table-eligible + res.numDfaStates = states.size(); + res.category = Category.CONTEXT_SENSITIVE; + return false; + } continue; } - for (Set succ : successors(configs, res)) { - Integer id = stateIds.get(succ); + for (LabeledSuccessor ls : successors(configs, res)) { + Integer id = stateIds.get(ls.configs); if (id == null) { if (states.size() >= maxDfaStates) { overflow = true; break; } id = states.size(); - stateIds.put(succ, id); - states.add(succ); + stateIds.put(ls.configs, id); + states.add(ls.configs); edges.add(new ArrayList()); - terminal.add(Boolean.FALSE); + edgeLabels.add(new ArrayList()); + acceptAlts.add(0); work.add(id); } edges.get(d).add(id); + edgeLabels.get(d).add(ls.label); } } @@ -350,15 +380,66 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { else if (!res.exactAmbigConflicts.isEmpty()) res.category = Category.EXACT_AMBIG; else if (cyclic) res.category = Category.LLSTAR; else res.category = Category.LLK; + + if (res.category == Category.LLK || res.category == Category.LLSTAR + || res.category == Category.EXACT_AMBIG) { + res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, cyclic, res.k); + } return false; } + /** Serialize the recorded DFA into the flat table form used by codegen. */ + protected static StaticDFA toStaticDFA(int decision, + List> edgeLabels, + List> edgeTargets, + List acceptAlts, + boolean cyclic, int maxK) { + int n = edgeTargets.size(); + int[] accepts = new int[n]; + int[] offsets = new int[n+1]; + List triples = new ArrayList(); + for (int s = 0; s < n; s++) { + accepts[s] = acceptAlts.get(s); + offsets[s] = triples.size()*3; + List stateTriples = new ArrayList(); + for (int e = 0; e < edgeTargets.get(s).size(); e++) { + int target = edgeTargets.get(s).get(e); + for (Interval iv : edgeLabels.get(s).get(e).getIntervals()) { + stateTriples.add(new int[]{iv.a, iv.b, target}); + } + } + // disjoint by construction; sort by lo for binary search + stateTriples.sort((a, b) -> Integer.compare(a[0], b[0])); + triples.addAll(stateTriples); + } + offsets[n] = triples.size()*3; + int[] edges = new int[triples.size()*3]; + for (int i = 0; i < triples.size(); i++) { + edges[i*3] = triples.get(i)[0]; + edges[i*3+1] = triples.get(i)[1]; + edges[i*3+2] = triples.get(i)[2]; + } + return new StaticDFA(decision, n, accepts, offsets, edges, cyclic, maxK); + } + + /** A DFA edge under construction: token class label -> successor config set. */ + protected static final class LabeledSuccessor { + final IntervalSet label; + final Set configs; + LabeledSuccessor(IntervalSet label, Set configs) { + this.label = label; + this.configs = configs; + } + } + /** - * Compute the distinct successor configuration sets of a DFA state, one - * per equivalence class of tokens (never per token). The labels - * themselves are not retained; Phase 0 only needs the DFA's shape. + * Compute the successor configuration sets of a DFA state, one edge per + * distinct successor set, labeled with the full token class (never per + * token). Token classes are the equivalence classes of the partition + * induced by the states' move labels; classes that close to the same + * successor set are merged into a single edge with the union label. */ - protected Collection> successors(Set configs, Result res) { + protected List successors(Set configs, Result res) { // collect non-epsilon moves List labels = new ArrayList(); List moveConfigs = new ArrayList(); @@ -396,22 +477,39 @@ else if (t instanceof WildcardTransition) { } } - // partition the token space into equivalence classes over move labels - TreeSet boundaries = new TreeSet(); + // partition the token space into equivalence classes over move labels: + // between two consecutive boundary points every token behaves alike + TreeSet boundarySet = new TreeSet(); for (IntervalSet label : labels) { for (Interval iv : label.getIntervals()) { - boundaries.add(iv.a); - boundaries.add(iv.b+1); + boundarySet.add(iv.a); + boundarySet.add(iv.b+1); } } + Integer[] boundaries = boundarySet.toArray(new Integer[0]); - Map> byMoveKey = new LinkedHashMap>(); - for (int p : boundaries) { + // accumulate the full label of each class (key = set of covering moves) + Map classLabels = new LinkedHashMap(); + for (int b = 0; b < boundaries.length-1; b++) { + int lo = boundaries[b]; + int hi = boundaries[b+1]-1; BitSet key = new BitSet(labels.size()); for (int m = 0; m < labels.size(); m++) { - if (labels.get(m).contains(p)) key.set(m); + if (labels.get(m).contains(lo)) key.set(m); + } + if (key.isEmpty()) continue; + IntervalSet classLabel = classLabels.get(key); + if (classLabel == null) { + classLabel = new IntervalSet(); + classLabels.put(key, classLabel); } - if (key.isEmpty() || byMoveKey.containsKey(key)) continue; + classLabel.add(lo, hi); + } + + // close each class; merge classes that reach the same successor set + Map, IntervalSet> bySuccessor = new LinkedHashMap, IntervalSet>(); + for (Map.Entry e : classLabels.entrySet()) { + BitSet key = e.getKey(); Set succ = new LinkedHashSet(); Set busy = new HashSet(); for (int m = key.nextSetBit(0); m >= 0; m = key.nextSetBit(m+1)) { @@ -423,10 +521,21 @@ else if (t instanceof WildcardTransition) { closure(new ATNConfig(c, moveTargets.get(m)), succ, busy, res); } } - byMoveKey.put(key, canonical(succ)); + succ = canonical(succ); + IntervalSet merged = bySuccessor.get(succ); + if (merged == null) { + bySuccessor.put(succ, e.getValue()); + } + else { + merged.addAll(e.getValue()); + } } - // distinct successor sets (different token classes may close to the same set) - return new LinkedHashSet>(byMoveKey.values()); + + List result = new ArrayList(bySuccessor.size()); + for (Map.Entry, IntervalSet> e : bySuccessor.entrySet()) { + result.add(new LabeledSuccessor(e.getValue(), e.getKey())); + } + return result; } /** @@ -604,6 +713,35 @@ private static int longestPathFrom(int s, List> edges, int[] memo) return max; } + // --------------------------------------------------------------------- + // Table building (codegen entry point) + // --------------------------------------------------------------------- + + /** + * Build serialized prediction tables for every decision that is + * statically decidable with behavior preservation and not already served + * by the LL(1) fast path. Everything else (the "unsafe residue": + * context-sensitive/overflow/predicated/non-greedy/LR-precedence + * decisions) is left to {@code adaptivePredict}. + */ + public static Map buildTables(Grammar g) { + DecisionClassifier classifier = new DecisionClassifier(g); + classifier.abortOnUntrustedConflict = true; + Map tables = new LinkedHashMap(); + for (DecisionState s : g.atn.decisionToState) { + // the LL(1) fast path already covers disjoint decisions + if (g.decisionLOOK != null && s.decision < g.decisionLOOK.size() + && AnalysisPipeline.disjoint(g.decisionLOOK.get(s.decision))) { + continue; + } + Result r = classifier.classify(s); + if (r.dfa != null) { + tables.put(s.decision, r.dfa); + } + } + return tables; + } + // --------------------------------------------------------------------- // Report // --------------------------------------------------------------------- diff --git a/tool/src/org/antlr/v4/analysis/StaticDFA.java b/tool/src/org/antlr/v4/analysis/StaticDFA.java new file mode 100644 index 0000000000..fe37f898b9 --- /dev/null +++ b/tool/src/org/antlr/v4/analysis/StaticDFA.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.analysis; + +/** + * A statically-precomputed SLL prediction DFA for a single parser decision, + * produced by {@link DecisionClassifier} for decisions whose static + * resolution is provably behavior-preserving (conflict-free LL(k)/LL(*) + * DFAs, plus trusted exact ambiguities resolved to the minimum alternative). + * + *

This is the compile-time equivalent of the DFA that + * {@code ParserATNSimulator} would otherwise build lazily at runtime in SLL + * mode. Code generation serializes it into the generated parser as constant + * tables; a tiny runtime walker ({@code dfaPredict}) drives prediction with + * no ATN simulation and no allocation.

+ * + *

Encoding: state 0 is the start state. {@link #accepts}{@code [s] > 0} + * marks an accept state predicting that alternative (alternative numbers are + * the decision state's transition indexes + 1, exactly like + * {@code adaptivePredict}'s return value). Accept states are terminal (no + * outgoing edges). Non-accept states carry sorted, disjoint edges + * {@code (lo, hi, target)} over token types (including {@code Token.EOF} = + * -1); a lookahead token matching no edge means no viable alternative.

+ */ +public class StaticDFA { + public final int decision; + public final int numStates; + /** Predicted alternative per state; 0 = not an accept state. */ + public final int[] accepts; + /** Index of each state's first edge int in {@link #edges}; length numStates+1. */ + public final int[] edgeOffsets; + /** Flattened (lo, hi, target) triples, sorted by lo within each state. */ + public final int[] edges; + /** True if the DFA contains cycles (unbounded, LL(*) lookahead). */ + public final boolean cyclic; + /** Max lookahead depth if acyclic; -1 if cyclic. */ + public final int maxK; + + public StaticDFA(int decision, int numStates, int[] accepts, + int[] edgeOffsets, int[] edges, boolean cyclic, int maxK) { + this.decision = decision; + this.numStates = numStates; + this.accepts = accepts; + this.edgeOffsets = edgeOffsets; + this.edges = edges; + this.cyclic = cyclic; + this.maxK = maxK; + } +} diff --git a/tool/src/org/antlr/v4/codegen/CompactSerializer.java b/tool/src/org/antlr/v4/codegen/CompactSerializer.java new file mode 100644 index 0000000000..0ea94d75a9 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/CompactSerializer.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen; + +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; + +/** + * Compact serialization of integer streams for embedding in generated code: + * each value is zigzag-mapped ({@code (v << 1) ^ (v >> 31)}, so small + * negative values stay small), encoded as an unsigned LEB128 varint, and the + * resulting byte stream is base64-encoded (standard alphabet, with padding) + * and split into fixed-width text lines that render as one string literal + * each - editor-friendly, and each literal stays far below Java's + * 65535-byte string constant limit. + * + *

Used for the Rust target's {@code _serializedATN} and for the static + * DFA prediction tables ({@code -Xstatic-dfa}); decoders live in the target + * runtimes ({@code serialized_ints} in Rust, + * {@code StaticDFATables} in Java).

+ */ +public class CompactSerializer { + /** Width of the emitted base64 lines. */ + public static final int LINE_CHARS = 80; + + /** Encode the values into base64 text lines of at most {@link #LINE_CHARS} chars. */ + public static List encode(int[] values) { + ByteBuffer buf = new ByteBuffer(); + for (int value : values) { + int v = (value << 1) ^ (value >> 31); // zigzag + while ((v & ~0x7F) != 0) { + buf.add((byte)((v & 0x7F) | 0x80)); + v >>>= 7; + } + buf.add((byte)v); + } + String base64 = Base64.getEncoder().encodeToString(buf.toArray()); + List lines = new ArrayList((base64.length()+LINE_CHARS-1)/LINE_CHARS); + for (int at = 0; at < base64.length(); at += LINE_CHARS) { + lines.add(base64.substring(at, Math.min(at+LINE_CHARS, base64.length()))); + } + return lines; + } + + private static final class ByteBuffer { + private byte[] data = new byte[8192]; + private int size; + + void add(byte b) { + if (size == data.length) { + byte[] bigger = new byte[data.length*2]; + System.arraycopy(data, 0, bigger, 0, size); + data = bigger; + } + data[size++] = b; + } + + byte[] toArray() { + byte[] result = new byte[size]; + System.arraycopy(data, 0, result, 0, size); + return result; + } + } +} diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index ade54e5eee..e6bc427730 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -13,6 +13,10 @@ import org.antlr.v4.codegen.model.Choice; import org.antlr.v4.codegen.model.CodeBlockForAlt; import org.antlr.v4.codegen.model.CodeBlockForOuterMostAlt; +import org.antlr.v4.codegen.model.DFAAltBlock; +import org.antlr.v4.codegen.model.DFAOptionalBlock; +import org.antlr.v4.codegen.model.DFAPlusBlock; +import org.antlr.v4.codegen.model.DFAStarBlock; import org.antlr.v4.codegen.model.InvokeRule; import org.antlr.v4.codegen.model.LL1AltBlock; import org.antlr.v4.codegen.model.LL1OptionalBlock; @@ -199,6 +203,9 @@ public Choice getChoiceBlock(BlockAST blkAST, List alts, Gramma if ( !g.tool.force_atn && AnalysisPipeline.disjoint(g.decisionLOOK.get(decision)) ) { c = getLL1ChoiceBlock(blkAST, alts); } + else if ( hasStaticDFA(decision) ) { + c = new DFAAltBlock(this, blkAST, alts); + } else { c = getComplexChoiceBlock(blkAST, alts); } @@ -235,11 +242,44 @@ else if ( ebnfRoot.getType()==ANTLRParser.CLOSURE ) { if ( AnalysisPipeline.disjoint(g.decisionLOOK.get(decision)) ) { return getLL1EBNFBlock(ebnfRoot, alts); } + + if ( hasStaticDFA(decision) ) { + return getDFAEBNFBlock(ebnfRoot, alts); + } } return getComplexEBNFBlock(ebnfRoot, alts); } + /** + * Is a statically-precomputed prediction table available (and usable by + * this target) for the given decision? See -Xstatic-dfa. + */ + protected boolean hasStaticDFA(int decision) { + return g.staticDecisionDFAs!=null + && g.staticDecisionDFAs.containsKey(decision) + && gen.getTarget().supportsStaticDFA(); + } + + /** Like getComplexEBNFBlock but driving the decision from a static DFA table. */ + protected Choice getDFAEBNFBlock(GrammarAST ebnfRoot, List alts) { + int ebnf = 0; + if ( ebnfRoot!=null ) ebnf = ebnfRoot.getType(); + Choice c = null; + switch ( ebnf ) { + case ANTLRParser.OPTIONAL : + c = new DFAOptionalBlock(this, ebnfRoot, alts); + break; + case ANTLRParser.CLOSURE : + c = new DFAStarBlock(this, ebnfRoot, alts); + break; + case ANTLRParser.POSITIVE_CLOSURE : + c = new DFAPlusBlock(this, ebnfRoot, alts); + break; + } + return c; + } + @Override public Choice getLL1ChoiceBlock(BlockAST blkAST, List alts) { return new LL1AltBlock(this, blkAST, alts); diff --git a/tool/src/org/antlr/v4/codegen/Target.java b/tool/src/org/antlr/v4/codegen/Target.java index 0a426601f4..c2324dd05a 100644 --- a/tool/src/org/antlr/v4/codegen/Target.java +++ b/tool/src/org/antlr/v4/codegen/Target.java @@ -658,4 +658,20 @@ public boolean isATNSerializedAsInts() { /** @since 4.14 */ public boolean supportsSplitParser() { return false; } + + /** + * Whether this target's templates and runtime implement table-driven + * static DFA prediction (-Xstatic-dfa): the SerializedStaticDFAs and + * DFA*Block templates plus a dfaPredict runtime helper. + */ + public boolean supportsStaticDFA() { return false; } + + /** + * Whether this target's serialized ATN is emitted as a compact + * base64/varint blob (see {@link org.antlr.v4.codegen.CompactSerializer}) + * decoded by the target runtime, instead of a plain integer list. The + * target's templates must render the SerializedBase64ATN model and its + * runtime must provide the matching decoder. + */ + public boolean isATNSerializedAsBase64VarInts() { return false; } } diff --git a/tool/src/org/antlr/v4/codegen/model/DFAAltBlock.java b/tool/src/org/antlr/v4/codegen/model/DFAAltBlock.java new file mode 100644 index 0000000000..e405b1cf67 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/DFAAltBlock.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.tool.ast.GrammarAST; + +import java.util.List; + +/** + * An alt block whose decision is driven by a statically-precomputed SLL + * prediction table ({@link SerializedStaticDFA}) via the runtime's + * dfaPredict walker instead of adaptivePredict. Structurally identical to + * {@link AltBlock}; only the prediction call differs in the template. + */ +public class DFAAltBlock extends AltBlock { + public DFAAltBlock(OutputModelFactory factory, + GrammarAST blkOrEbnfRootAST, + List alts) + { + super(factory, blkOrEbnfRootAST, alts); + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/DFAOptionalBlock.java b/tool/src/org/antlr/v4/codegen/model/DFAOptionalBlock.java new file mode 100644 index 0000000000..27271cb546 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/DFAOptionalBlock.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.tool.ast.GrammarAST; + +import java.util.List; + +/** + * An optional block whose decision is driven by a statically-precomputed + * SLL prediction table via the runtime's dfaPredict walker instead of + * adaptivePredict. Structurally identical to {@link OptionalBlock}. + */ +public class DFAOptionalBlock extends OptionalBlock { + public DFAOptionalBlock(OutputModelFactory factory, + GrammarAST questionAST, + List alts) + { + super(factory, questionAST, alts); + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/DFAPlusBlock.java b/tool/src/org/antlr/v4/codegen/model/DFAPlusBlock.java new file mode 100644 index 0000000000..4b3390ff7e --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/DFAPlusBlock.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.tool.ast.GrammarAST; + +import java.util.List; + +/** + * A plus loop whose continue/exit decision is driven by a statically- + * precomputed SLL prediction table via the runtime's dfaPredict walker + * instead of adaptivePredict. Structurally identical to {@link PlusBlock} + * (subclassing also keeps SourceGenTriggers' hasLookaheadBlock/_alt + * declaration logic working). + */ +public class DFAPlusBlock extends PlusBlock { + public DFAPlusBlock(OutputModelFactory factory, + GrammarAST plusRoot, + List alts) + { + super(factory, plusRoot, alts); + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/DFAStarBlock.java b/tool/src/org/antlr/v4/codegen/model/DFAStarBlock.java new file mode 100644 index 0000000000..f033e5e0d2 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/DFAStarBlock.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.tool.ast.GrammarAST; + +import java.util.List; + +/** + * A star loop whose enter/exit decision is driven by a statically- + * precomputed SLL prediction table via the runtime's dfaPredict walker + * instead of adaptivePredict. Structurally identical to {@link StarBlock} + * (subclassing also keeps SourceGenTriggers' hasLookaheadBlock/_alt + * declaration logic working). + */ +public class DFAStarBlock extends StarBlock { + public DFAStarBlock(OutputModelFactory factory, + GrammarAST blkOrEbnfRootAST, + List alts) + { + super(factory, blkOrEbnfRootAST, alts); + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/Parser.java b/tool/src/org/antlr/v4/codegen/model/Parser.java index 4e5e135f17..de556a814e 100644 --- a/tool/src/org/antlr/v4/codegen/model/Parser.java +++ b/tool/src/org/antlr/v4/codegen/model/Parser.java @@ -7,6 +7,7 @@ package org.antlr.v4.codegen.model; import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.tool.Grammar; import java.util.ArrayList; import java.util.List; @@ -16,8 +17,26 @@ public class Parser extends Recognizer { @ModelElement public List funcs = new ArrayList(); + /** + * All statically-precomputed SLL prediction tables (-Xstatic-dfa), + * packed into one compact serialized blob deserialized by the target + * runtime (in the same vein as the serialized ATN); null unless tables + * exist and the target supports static DFA prediction. Targets using + * the compact base64 ATN encoding (Rust) carry the tables inside the + * ATN blob instead (see {@link SerializedBase64ATN}) and leave this + * null. Targets whose Parser template lacks the staticDFAs formal + * argument are unaffected (the model walker skips unknown fields). + */ + @ModelElement public SerializedStaticDFAs staticDFAs; + public Parser(OutputModelFactory factory, ParserFile file) { super(factory); this.file = file; // who contains us? + Grammar g = factory.getGrammar(); + if ( g.staticDecisionDFAs!=null && !g.staticDecisionDFAs.isEmpty() + && factory.getGenerator().getTarget().supportsStaticDFA() + && !factory.getGenerator().getTarget().isATNSerializedAsBase64VarInts() ) { + staticDFAs = new SerializedStaticDFAs(factory, g.staticDecisionDFAs); + } } } diff --git a/tool/src/org/antlr/v4/codegen/model/Recognizer.java b/tool/src/org/antlr/v4/codegen/model/Recognizer.java index 732f50fb20..2965098e80 100644 --- a/tool/src/org/antlr/v4/codegen/model/Recognizer.java +++ b/tool/src/org/antlr/v4/codegen/model/Recognizer.java @@ -68,6 +68,9 @@ public Recognizer(OutputModelFactory factory) { if ( gen.getTarget() instanceof JavaTarget ) { atn = new SerializedJavaATN(factory, g.atn); } + else if ( gen.getTarget().isATNSerializedAsBase64VarInts() ) { + atn = new SerializedBase64ATN(factory, g.atn); + } else { atn = new SerializedATN(factory, g.atn); } diff --git a/tool/src/org/antlr/v4/codegen/model/SerializedBase64ATN.java b/tool/src/org/antlr/v4/codegen/model/SerializedBase64ATN.java new file mode 100644 index 0000000000..69b73709d1 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/SerializedBase64ATN.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.CompactSerializer; +import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.misc.IntegerList; +import org.antlr.v4.tool.Grammar; + +import java.util.ArrayList; +import java.util.List; + +/** + * A serialized ATN encoded with {@link CompactSerializer} (zigzag LEB128 + * varints, base64, 80-column lines) for targets whose runtime deserializes + * the int stream itself (currently Rust; see {@code serialized_ints} and + * {@code ATNDeserializer::deserialize_compact} in the Rust runtime). + * Roughly 2-3x smaller in generated-source bytes than the plain decimal int + * list, and far fewer tokens for the target compiler to parse. + * + *

When the grammar has statically-precomputed SLL prediction tables + * ({@code -Xstatic-dfa}), their serialized stream (see + * {@link SerializedStaticDFAs}) is appended after the ATN ints so the + * runtime decodes both from the single blob in one streaming pass; the + * tables land in the ATN's {@code static_dfas} field.

+ */ +public class SerializedBase64ATN extends SerializedATN { + public final List segments; + /** One provenance line per appended static DFA table; empty if none. */ + public final List tableComments = new ArrayList(); + public final int numTables; + + public SerializedBase64ATN(OutputModelFactory factory, ATN atn) { + super(factory, atn); + IntegerList data = new IntegerList(); + for (int v : serialized) data.add(v); + + Grammar g = factory.getGrammar(); + if ( g.staticDecisionDFAs!=null && !g.staticDecisionDFAs.isEmpty() + && g.atn==atn + && factory.getGenerator().getTarget().supportsStaticDFA() ) { + SerializedStaticDFAs.appendIntStream(g.staticDecisionDFAs, data, tableComments); + } + numTables = tableComments.size(); + + segments = CompactSerializer.encode(data.toArray()); + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java new file mode 100644 index 0000000000..8dba2829fd --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.analysis.StaticDFA; +import org.antlr.v4.codegen.CompactSerializer; +import org.antlr.v4.codegen.OutputModelFactory; +import org.antlr.v4.runtime.misc.IntegerList; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * All statically-precomputed SLL prediction tables of a parser + * (see {@link StaticDFA}), packed into one compact serialized blob - + * in the same vein as {@code _serializedATN} - and lazily deserialized by + * the target runtime's {@code StaticDFATables} at first use. + * + *

The logical int stream below is encoded with + * {@link CompactSerializer} (zigzag LEB128 varints, base64, 80-column line + * segments; runtimes concatenate all segments before decoding):

+ * + *
+ * FORMAT_VERSION
+ * numTables
+ * numDecisionSlots                  (max decision number + 1)
+ * for each table:
+ *   decision
+ *   numStates
+ *   numEdgeInts
+ *   accepts[numStates]              (predicted alt per state; 0 = non-accept)
+ *   edgeOffsets[numStates+1]        (index of each state's first edge int)
+ *   edges[numEdgeInts]              ((lo, hi, target) triples, lo-sorted per state)
+ * 
+ */ +public class SerializedStaticDFAs extends OutputModelObject { + public static final int FORMAT_VERSION = 2; + + public final int numTables; + /** Base64 text segments of the serialized blob, one rendered per line. */ + public final List segments; + /** One human-readable provenance line per table, for a generated comment. */ + public final List tableComments = new ArrayList(); + + public SerializedStaticDFAs(OutputModelFactory factory, Map dfas) { + super(factory); + this.numTables = dfas.size(); + IntegerList data = new IntegerList(); + appendIntStream(dfas, data, tableComments); + segments = CompactSerializer.encode(data.toArray()); + } + + /** + * Append the logical int stream for the tables to {@code data} and one + * provenance line per table to {@code comments}. Shared with + * {@link SerializedBase64ATN}, which appends the stream after the ATN + * ints so both are decoded from a single blob. + */ + public static void appendIntStream(Map dfas, + IntegerList data, + List comments) { + int numDecisionSlots = 0; + for (StaticDFA dfa : dfas.values()) { + numDecisionSlots = Math.max(numDecisionSlots, dfa.decision+1); + } + + data.add(FORMAT_VERSION); + data.add(dfas.size()); + data.add(numDecisionSlots); + for (StaticDFA dfa : dfas.values()) { + data.add(dfa.decision); + data.add(dfa.numStates); + data.add(dfa.edges.length); + for (int v : dfa.accepts) data.add(v); + for (int v : dfa.edgeOffsets) data.add(v); + for (int v : dfa.edges) data.add(v); + comments.add("decision "+dfa.decision+": " + +(dfa.cyclic ? "LL(*) cyclic" : "LL(k), k="+dfa.maxK) + +", "+dfa.numStates+" states"); + } + } +} diff --git a/tool/src/org/antlr/v4/codegen/target/JavaTarget.java b/tool/src/org/antlr/v4/codegen/target/JavaTarget.java index 71bd8e46ef..71ec072844 100644 --- a/tool/src/org/antlr/v4/codegen/target/JavaTarget.java +++ b/tool/src/org/antlr/v4/codegen/target/JavaTarget.java @@ -60,6 +60,9 @@ public boolean isATNSerializedAsInts() { @Override public boolean supportsSplitParser() { return true; } + @Override + public boolean supportsStaticDFA() { return true; } + @Override public String getRecognizerFileName(SourceType sourceType) { ST extST = getTemplates().getInstanceOf("codeFileExtension"); diff --git a/tool/src/org/antlr/v4/codegen/target/RustTarget.java b/tool/src/org/antlr/v4/codegen/target/RustTarget.java index e0bbe8ad76..bcfab8af12 100644 --- a/tool/src/org/antlr/v4/codegen/target/RustTarget.java +++ b/tool/src/org/antlr/v4/codegen/target/RustTarget.java @@ -94,4 +94,10 @@ public String getBaseVisitorFileName(SourceType sourceType) { public int getInlineTestSetWordSize() { return 32; } + + @Override + public boolean supportsStaticDFA() { return true; } + + @Override + public boolean isATNSerializedAsBase64VarInts() { return true; } } diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index eabee9175f..bfb4a5722c 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -188,6 +188,14 @@ public class Grammar implements AttributeResolver { public List decisionLOOK; + /** + * Statically-precomputed SLL prediction tables (see + * {@link org.antlr.v4.analysis.DecisionClassifier#buildTables}), keyed by + * decision number; populated only with -Xstatic-dfa. Decisions absent + * from this map fall back to the LL(1) fast path or adaptivePredict. + */ + public Map staticDecisionDFAs; + public final Tool tool; /** Token names and literal tokens like "void" are uniquely indexed. From 24b8e2e85d798165f262d3e6d59ee7bd8c271098 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Thu, 9 Jul 2026 18:56:51 -0400 Subject: [PATCH 03/48] Runtime testsuite for static DFA prediction + two fixes it caught Add rust.RustStaticDFARuntimeTests: runs the full runtime-test descriptor corpus against the Rust target with -Xstatic-dfa (via RustStaticDFARunner). Expected outputs were authored against adaptive_predict, so the corpus acts as a broad differential test of the table-driven path. Descriptors that introspect the adaptive engine itself (showDiagnosticErrors, traceATN) are excluded through a new overridable RuntimeTests.skipDescriptor() hook: ambiguity and full-context diagnostics are reported from inside adaptive_predict, which statically-decided decisions bypass by design. The suite caught two real bugs, both fixed here: 1. Dangling-else mis-parse (IfIfElseNonGreedyBinding2): an exact SLL conflict whose epsilon-alternative reaches the conflict only by popping through the decision-entry wildcard into phantom FOLLOW contexts is NOT a context-independent ambiguity - full-context prediction kills that alternative under the real stack. Reinstate BOUNDARY_TAINT (marked when closure pops through the decision boundary, mirroring the runtime's reachesIntoOuterContext bookkeeping) and require uniform boundary usage for a trusted exact ambiguity: either no conflicting config crossed the boundary or all did. Mixed usage falls back to adaptivePredict. Taint bits are ordered so ATNConfigSet's max-merge can only lose the boundary bit in favor of hard bits, which demote regardless. Costs only 1-3 tables per real-world SQL grammar. 2. Wrong error class (NoViableAltAvoidance): on a failed reach, adaptivePredict returns the minimum alternative that already finished the decision entry rule, letting the parser report a precise mismatched-input error later, instead of throwing NoViableAlt immediately. Tables now carry a per-state fallbacks[] array (the static analogue of getAltThatFinishedDecisionEntryRule, derived from boundary-tainted configs) consulted by both walkers on dead edges. Static DFA wire format bumped to v3. Verified: RustStaticDFARuntimeTests 345/345, RustRuntimeTests baseline 362/362, full cargo test, Java differential probe 24/24, tool-testsuite 694 green. Signed-off-by: Bo Lin --- .../antlr/v4/test/runtime/RuntimeTests.java | 11 ++ .../runtime/rust/RustStaticDFARunner.java | 27 ++++ .../rust/RustStaticDFARuntimeTests.java | 37 ++++++ .../Java/src/org/antlr/v4/runtime/Parser.java | 7 + .../antlr/v4/runtime/atn/StaticDFATables.java | 37 ++++-- runtime/Rust/src/parser.rs | 8 ++ runtime/Rust/src/static_dfa.rs | 36 ++++- runtime/Rust/tests/gen/staticdfaparser.rs | 9 +- .../antlr/v4/analysis/DecisionClassifier.java | 124 ++++++++++++++---- tool/src/org/antlr/v4/analysis/StaticDFA.java | 12 +- .../codegen/model/SerializedStaticDFAs.java | 4 +- 11 files changed, 260 insertions(+), 52 deletions(-) create mode 100644 runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARunner.java create mode 100644 runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARuntimeTests.java diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeTests.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeTests.java index 09931d0864..621ee2b0ef 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeTests.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeTests.java @@ -41,6 +41,14 @@ public abstract class RuntimeTests { protected abstract RuntimeRunner createRuntimeRunner(); + /** + * Subclasses may exclude descriptors that do not apply to their + * configuration (e.g. the Rust static-DFA suite skips descriptors that + * introspect the adaptive prediction engine). Skipped descriptors are + * not materialized as tests at all. + */ + protected boolean skipDescriptor(RuntimeTestDescriptor descriptor) { return false; } + private final static HashMap testDescriptors = new HashMap<>(); private final static Map cachedTargetTemplates = new HashMap<>(); private final static StringRenderer rendered = new StringRenderer(); @@ -96,6 +104,9 @@ public List runtimeTests() { ArrayList descriptorTests = new ArrayList<>(); RuntimeTestDescriptor[] descriptors = testDescriptors.get(group); for (RuntimeTestDescriptor descriptor : descriptors) { + if (skipDescriptor(descriptor)) { + continue; + } descriptorTests.add(dynamicTest(descriptor.name, descriptor.uri, () -> { try (RuntimeRunner runner = createRuntimeRunner()) { String errorMessage = test(descriptor, runner); diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARunner.java new file mode 100644 index 0000000000..68a2a7032b --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARunner.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ +package org.antlr.v4.test.runtime.rust; + +import org.antlr.v4.test.runtime.RunOptions; + +import java.util.List; + +/** + * A {@link RustRunner} that generates the recognizers with + * {@code -Xstatic-dfa}, so every statically-decidable decision is driven by + * a precomputed prediction table instead of {@code adaptive_predict}. Used + * by {@link RustStaticDFARuntimeTests} to run the descriptor corpus as a + * large differential test: expected outputs were authored against adaptive + * prediction, so any deviation of the table-driven path fails the test. + */ +public class RustStaticDFARunner extends RustRunner { + @Override + protected List getTargetToolOptions(RunOptions ro) { + List options = super.getTargetToolOptions(ro); + options.add("-Xstatic-dfa"); + return options; + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARuntimeTests.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARuntimeTests.java new file mode 100644 index 0000000000..7f5c3eec8b --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARuntimeTests.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.test.runtime.rust; + +import org.antlr.v4.test.runtime.RuntimeRunner; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.RuntimeTests; + +/** + * Runs the full runtime-test descriptor corpus against the Rust target with + * {@code -Xstatic-dfa} enabled (see {@link RustStaticDFARunner}). Since all + * expected outputs were authored against {@code adaptive_predict}, this + * suite is a broad differential test of the table-driven static prediction + * path: parse trees, matched text, and error messages must be identical. + * + *

Descriptors that introspect the adaptive prediction engine itself are + * excluded: ambiguity/full-context diagnostics ({@code showDiagnosticErrors}) + * and ATN traces ({@code traceATN}) are reported from inside + * {@code adaptive_predict}, which statically-decided decisions bypass by + * design (a trusted exact ambiguity, for example, is resolved to its minimum + * alternative by the table without a runtime ambiguity report).

+ */ +public class RustStaticDFARuntimeTests extends RuntimeTests { + @Override + protected RuntimeRunner createRuntimeRunner() { + return new RustStaticDFARunner(); + } + + @Override + protected boolean skipDescriptor(RuntimeTestDescriptor descriptor) { + return descriptor.showDiagnosticErrors || descriptor.traceATN; + } +} diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java index 274a2604fb..1b41e0ce02 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java @@ -553,6 +553,13 @@ public int dfaPredict(StaticDFATables tables, int decision) if ( alt>0 ) return alt; int next = tables.edge(decision, s, _input.LA(i)); if ( next<0 ) { + // No viable transition. If some alternative already finished + // the decision entry rule, predict it and let the parser + // report a more precise error at the actual mismatch point - + // mirroring adaptivePredict's recovery via + // getAltThatFinishedDecisionEntryRule. + int fallback = tables.fallback(decision, s); + if ( fallback>0 ) return fallback; throw new NoViableAltException(this, _input, _input.LT(1), _input.LT(i), null, _ctx); diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java index 00fb2294d4..1237cbe924 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java @@ -31,6 +31,7 @@ * numStates * numEdgeInts * accepts[numStates] (predicted alt per state; 0 = non-accept) + * fallbacks[numStates] (error-avoidance alt per state; 0 = none) * edgeOffsets[numStates+1] (index of each state's first edge int) * edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) * @@ -44,11 +45,11 @@ */ public class StaticDFATables { /** Must match the tool's SerializedStaticDFAs.FORMAT_VERSION. */ - public static final int FORMAT_VERSION = 2; + public static final int FORMAT_VERSION = 3; - /** Concatenated per-table data: accepts, edgeOffsets, edges. */ + /** Concatenated per-table data: accepts, fallbacks, edgeOffsets, edges. */ protected final int[] data; - /** Per-table (acceptsAt, edgeOffsetsAt, edgesAt, endAt) indexes into {@link #data}. */ + /** Per-table (acceptsAt, fallbacksAt, edgeOffsetsAt, edgesAt, endAt) indexes into {@link #data}. */ protected final int[] metas; /** decision number -> table index, or -1. */ protected final int[] decisionToTable; @@ -82,7 +83,7 @@ public static StaticDFATables deserialize(String[] segments) { int[] decisionToTable = new int[numSlots]; java.util.Arrays.fill(decisionToTable, -1); - int[] metas = new int[numTables*4]; + int[] metas = new int[numTables*5]; // first pass over structure requires data sizes; buffer grows as we read IntBuffer data = new IntBuffer(); @@ -92,13 +93,15 @@ public static StaticDFATables deserialize(String[] segments) { int numEdgeInts = ints.next(); decisionToTable[decision] = table; - metas[table*4] = data.size; // acceptsAt + metas[table*5] = data.size; // acceptsAt for (int i = 0; i < numStates; i++) data.add(ints.next()); - metas[table*4+1] = data.size; // edgeOffsetsAt + metas[table*5+1] = data.size; // fallbacksAt + for (int i = 0; i < numStates; i++) data.add(ints.next()); + metas[table*5+2] = data.size; // edgeOffsetsAt for (int i = 0; i < numStates+1; i++) data.add(ints.next()); - metas[table*4+2] = data.size; // edgesAt + metas[table*5+3] = data.size; // edgesAt for (int i = 0; i < numEdgeInts; i++) data.add(ints.next()); - metas[table*4+3] = data.size; // endAt + metas[table*5+4] = data.size; // endAt } if (!ints.atEnd()) { throw new IllegalStateException("trailing bytes in static DFA blob"); @@ -108,15 +111,27 @@ public static StaticDFATables deserialize(String[] segments) { /** Predicted alternative if {@code state} of {@code decision}'s table accepts; else 0. */ public int accept(int decision, int state) { - int acceptsAt = metas[decisionToTable[decision]*4]; + int acceptsAt = metas[decisionToTable[decision]*5]; return data[acceptsAt+state]; } + /** + * Error-avoidance fallback alternative of {@code state}, or 0: the + * minimum alternative that already finished the decision entry rule, + * returned when no edge matches so the parser reports a more precise + * error at the actual mismatch point (mirroring adaptivePredict's + * getAltThatFinishedDecisionEntryRule recovery). + */ + public int fallback(int decision, int state) { + int fallbacksAt = metas[decisionToTable[decision]*5+1]; + return data[fallbacksAt+state]; + } + /** Successor of {@code state} on token {@code t}, or -1 (binary search). */ public int edge(int decision, int state, int t) { int table = decisionToTable[decision]; - int edgeOffsetsAt = metas[table*4+1]; - int edgesAt = metas[table*4+2]; + int edgeOffsetsAt = metas[table*5+2]; + int edgesAt = metas[table*5+3]; int lo = data[edgeOffsetsAt+state]/3; int hi = data[edgeOffsetsAt+state+1]/3 - 1; while (lo <= hi) { diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 3033ec9e89..13e2a2766f 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -494,6 +494,14 @@ where i += 1; } None => { + // No viable transition. If some alternative already + // finished the decision entry rule, predict it and let + // the parser report a more precise error at the actual + // mismatch point - mirroring adaptive_predict's + // finished-decision-entry-rule recovery. + if let Some(alt) = dfa.fallback(s) { + return Ok(alt); + } let start = self.input.lt(1).map(|t| OwningToken::from(t as &dyn Token)); let offending = self.input.lt(i).map(|t| OwningToken::from(t as &dyn Token)); return Err(match (start, offending) { diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs index 00d7c7a5a4..4c95fcbb18 100644 --- a/runtime/Rust/src/static_dfa.rs +++ b/runtime/Rust/src/static_dfa.rs @@ -25,13 +25,14 @@ //! numStates //! numEdgeInts //! accepts[numStates] (predicted alt per state; 0 = non-accept) +//! fallbacks[numStates] (error-avoidance alt per state; 0 = none) //! edgeOffsets[numStates+1] (index of each state's first edge i32) //! edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) //! ``` /// Format version understood by this runtime; must match the tool's /// `SerializedStaticDFAs.FORMAT_VERSION`. -pub const FORMAT_VERSION: i32 = 2; +pub const FORMAT_VERSION: i32 = 3; /// The deserialized static prediction tables of one generated parser. /// @@ -46,10 +47,10 @@ pub const FORMAT_VERSION: i32 = 2; /// consumes one token of lookahead and the input is finite (EOF included in /// the token space). pub struct StaticDFATables { - /// Concatenated per-table data: accepts, edge_offsets, edges. + /// Concatenated per-table data: accepts, fallbacks, edge_offsets, edges. data: Vec, - /// Per-table (accepts_at, edge_offsets_at, edges_at) indexes into `data`. - metas: Vec<(usize, usize, usize)>, + /// Per-table (accepts_at, fallbacks_at, edge_offsets_at, edges_at) indexes into `data`. + metas: Vec<(usize, usize, usize, usize)>, /// decision number -> table index, or -1. decision_to_table: Vec, } @@ -59,6 +60,11 @@ pub struct StaticDFATables { pub struct StaticDFATable<'a> { /// Predicted alternative per state; 0 = not an accept state. pub accepts: &'a [i32], + /// Error-avoidance fallback per state; 0 = none. Returned when a + /// lookahead token matches no edge, so the parser fails later with a + /// more precise error at the mismatch point - mirroring + /// `adaptive_predict`'s finished-decision-entry-rule recovery. + pub fallbacks: &'a [i32], /// Index of each state's first edge `i32` in `edges`; `num_states + 1` entries. pub edge_offsets: &'a [i32], /// Flattened `(lo, hi, target)` triples, sorted by `lo` within each state. @@ -111,6 +117,10 @@ impl StaticDFATables { for _ in 0..num_states { data.push(next()); } + let fallbacks_at = data.len(); + for _ in 0..num_states { + data.push(next()); + } let edge_offsets_at = data.len(); for _ in 0..num_states + 1 { data.push(next()); @@ -119,7 +129,7 @@ impl StaticDFATables { for _ in 0..num_edge_ints { data.push(next()); } - metas.push((accepts_at, edge_offsets_at, edges_at)); + metas.push((accepts_at, fallbacks_at, edge_offsets_at, edges_at)); } drop(next); assert!(ints.next().is_none(), "trailing data in static DFA blob"); @@ -137,14 +147,15 @@ impl StaticDFATables { pub fn table(&self, decision: i32) -> StaticDFATable<'_> { let t = self.decision_to_table[decision as usize]; assert!(t >= 0, "no static DFA table for decision {}", decision); - let (accepts_at, edge_offsets_at, edges_at) = self.metas[t as usize]; + let (accepts_at, fallbacks_at, edge_offsets_at, edges_at) = self.metas[t as usize]; let end = self .metas .get(t as usize + 1) .map(|m| m.0) .unwrap_or(self.data.len()); StaticDFATable { - accepts: &self.data[accepts_at..edge_offsets_at], + accepts: &self.data[accepts_at..fallbacks_at], + fallbacks: &self.data[fallbacks_at..edge_offsets_at], edge_offsets: &self.data[edge_offsets_at..edges_at], edges: &self.data[edges_at..end], } @@ -163,6 +174,17 @@ impl<'a> StaticDFATable<'a> { } } + /// Error-avoidance fallback alternative of `state`, if any. + #[inline] + pub fn fallback(&self, state: usize) -> Option { + let alt = self.fallbacks[state]; + if alt > 0 { + Some(alt) + } else { + None + } + } + /// Successor of `state` on token type `t`, if any (binary search). #[inline] pub fn edge(&self, state: usize, t: i32) -> Option { diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index 6075f49909..990732ad85 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -1816,7 +1816,7 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); -static _serializedATN: [&'static str; 13] = [ +static _serializedATN: [&'static str; 14] = [ "CAIckgEEAA4ABAIOAgQEDgQEBg4GBAgOCAQKDgoEDA4MAgACAAIAAgACAAIAAgACAAIABgAwEAACAgIC", "AgICAgICBgI+EAICBAIEAgQKBEgQBBQEGAROEgQCBgIGCgZWEAYUBhgGXBIGAgYCBgIGAggCCAgIahAI", "FggYCGwCCAIIAggCCgIKBgp8EAoCCgIKAgoCDAIMAgwCDAYMjgEQDAIMAAAOAAQIDBAUGAAAkgEALgIA", @@ -1827,7 +1827,8 @@ static _serializedATN: [&'static str; 13] = [ "AAAAWFQCAAAAWFoCAAAAWl4CAAAAXFgCAAAAXmAKEAAAYGIKFAAAYg4CAAAAZGYKEAAAZmoKEgAAaGQC", "AAAAamwCAAAAbGgCAAAAbG4CAAAAbnACAAAAcHIKEAAAcnQKFAAAdBICAAAAdngKEAAAeHwKEgAAenYC", "AAAAenwCAAAAfH4CAAAAfoABChAAAIABggEKFAAAggEWAgAAAIQBhgEKFgAAhgGOAQoYAACIAYoBChYA", - "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEEDA4AChgAAAYCBAAMGBgYGAIC", - "AggIBAQEBgYGCAIKHgAABAIAAAYYGBgeGhoCAQEECgoGDg4IGhoCBggSAAACBAAGEhISEBACEhIEFBQG", - "CAgSAAACBAAGEhISEBACEhIEFBQGCggSAAACBAAGEhISEBACEhIEFBQGDAYMAAACAAYMDBYWAhgYBA==" + "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEGDA4AChgAAAYCBAAAAAAAAAwY", + "GBgYAgICCAgEBAQGBgYIAgoeAAAEAgAABAAAAAAGGBgYHhoaAgEBBAoKBg4OCBoaAgYIEgAAAgQAAAAA", + "AAYSEhIQEAISEgQUFAYICBIAAAIEAAAAAAAGEhISEBACEhIEFBQGCggSAAACBAAAAAAABhISEhAQAhIS", + "BBQUBgwGDAAAAgAAAAAGDAwWFgIYGAQ=" ]; \ No newline at end of file diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 39d5f921e5..2740b6d2ec 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -143,32 +143,59 @@ public Result(DecisionState decisionState) { /** * Taint bits stored in {@link ATNConfig#reachesIntoOuterContext} marking - * configurations derived through an over-approximation. The field is - * chosen because every ATNConfig copy constructor propagates it, - * ATNConfigSet's merge takes the max of it, and equals/hashCode ignore it - * - so the taint flows to closure descendants and survives merging - * without affecting DFA state identity. (This classifier never uses the - * field's runtime meaning; note max-merge is bitwise-correct here only - * because tainted values compare greater than untainted ones and we only - * test for non-zero.) + * how configurations were derived. The field is chosen because every + * ATNConfig copy constructor propagates it, ATNConfigSet's merge takes + * the max of it, and equals/hashCode ignore it - so the taint flows to + * closure descendants and survives merging without affecting DFA state + * identity. (This classifier never uses the field's runtime meaning.) * - *

Over-approximations are one-sided: they can only keep alternatives - * alive longer than the runtime would, so uniquely-predicted accepts - * remain correct, but a conflict involving tainted configurations may be - * an analysis artifact the runtime never encounters and must not be - * trusted as an exact ambiguity.

+ *

Because merging takes the numeric max rather than the bitwise or, + * the "hard" bits ({@link #PRECPRED_TAINT}, {@link #WIDENED_TAINT}) are + * assigned above {@link #BOUNDARY_TAINT}: a merge can only lose the + * boundary bit in favor of a hard bit, and hard-tainted conflicts are + * untrusted regardless. When no hard taint is present in a + * configuration set, the boundary bits are exact.

+ * + *

Over-approximations (widening, assumed-true precedence predicates) + * are one-sided: they can only keep alternatives alive longer than the + * runtime would, so uniquely-predicted accepts remain correct, but any + * conflict involving such configurations may be an analysis artifact the + * runtime never encounters and must not be trusted as an exact + * ambiguity.

+ */ + /** + * Taint for configurations derived by popping through the decision-entry + * wildcard context (the SLL boundary): their continuations come from the + * grammar-wide FOLLOW links rather than the real parse stack. This + * mirrors the runtime's own {@code reachesIntoOuterContext} bookkeeping. + * + *

An exact conflict is context-independent - and therefore a true + * ambiguity resolvable to the minimum alternative - only if boundary + * usage is uniform: either no conflicting configuration popped + * through the boundary (the conflict is internal to the decision's + * sub-language) or all of them did (the real outer context substitutes + * into every alternative identically). Mixed usage is the dangling-else + * shape: one alternative reaches the conflict only via phantom follow + * contexts, and full-context prediction may kill it.

+ * + *

Boundary-tainted configurations also identify the alternatives + * that "finished the decision entry rule", used for the per-state + * error-avoidance fallback (see {@link StaticDFA#fallbacks}), mirroring + * ParserATNSimulator#getAltThatFinishedDecisionEntryRule.

*/ - protected static final int WIDENED_TAINT = 1; + protected static final int BOUNDARY_TAINT = 1; /** * Taint for configurations that traversed a precedence predicate as - * epsilon (i.e., assumed {@code precpred(...)} true). Same one-sided - * soundness argument as {@link #WIDENED_TAINT}. + * epsilon (i.e., assumed {@code precpred(...)} true). */ protected static final int PRECPRED_TAINT = 2; - /** All taint bits that make a conflict untrusted. */ - protected static final int ANY_TAINT = WIDENED_TAINT | PRECPRED_TAINT; + /** Taint for configurations whose calling context was widened. */ + protected static final int WIDENED_TAINT = 4; + + /** Taint bits that make any conflict untrusted outright. */ + protected static final int HARD_TAINT = WIDENED_TAINT | PRECPRED_TAINT; /** Hard cap on DFA states per decision (per construction attempt). */ public int maxDfaStates = 2000; @@ -287,6 +314,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List> edges = new ArrayList>(); List> edgeLabels = new ArrayList>(); List acceptAlts = new ArrayList(); // 0 = not an accept state + List fallbackAlts = new ArrayList(); // 0 = none Set start = new LinkedHashSet(); Set startBusy = new HashSet(); @@ -300,6 +328,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { edges.add(new ArrayList()); edgeLabels.add(new ArrayList()); acceptAlts.add(0); + fallbackAlts.add(0); Deque work = new ArrayDeque(); work.add(0); @@ -322,21 +351,36 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { Collection altSubsets = PredictionMode.getConflictingAltSubsets(cs); boolean exact = PredictionMode.allSubsetsConflict(altSubsets) && PredictionMode.allSubsetsEqual(altSubsets); - boolean tainted = false; + boolean hardTainted = false; + boolean anyBoundary = false; + boolean allBoundary = true; for (ATNConfig c : cs) { - if ((c.reachesIntoOuterContext & ANY_TAINT) != 0) { tainted = true; break; } + if ((c.reachesIntoOuterContext & HARD_TAINT) != 0) hardTainted = true; + if ((c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0) anyBoundary = true; + else allBoundary = false; } + // A conflict is trusted as an exact ambiguity only if it is + // exact, involves no over-approximated (hard-tainted) + // configs, and its boundary usage is uniform: either the + // conflict is internal to the decision's sub-language, or + // every config popped through the decision boundary so the + // real outer context substitutes into all alternatives + // identically. Mixed usage (dangling-else shape) means + // full-context prediction may kill the boundary-only + // alternative, so min-alt is not behavior-preserving. + boolean untrusted = hardTainted || (anyBoundary && !allBoundary); BitSet conflicting = PredictionMode.getAlts(altSubsets); - if (tainted) res.approxConflicts.add(conflicting); + if (untrusted) res.approxConflicts.add(conflicting); else if (exact) res.exactAmbigConflicts.add(conflicting); else res.contextSensitiveConflicts.add(conflicting); - if (!tainted && exact) { + if (!untrusted && exact) { // trusted exact ambiguity: min-alt resolution matches // both runtime SLL and full-context LL acceptAlts.set(d, conflicting.nextSetBit(0)); } else if (abortOnUntrustedConflict) { - // no widening level can make this decision table-eligible + // not a trusted exact ambiguity: no widening level can + // make this decision table-eligible res.numDfaStates = states.size(); res.category = Category.CONTEXT_SENSITIVE; return false; @@ -344,6 +388,23 @@ else if (abortOnUntrustedConflict) { continue; } + // Error-avoidance fallback for this (expanding) state: the + // minimum alternative that already "finished the decision entry + // rule" (popped through the decision boundary). When prediction + // later dies at this state on a token matching no edge, the + // walker returns this alternative instead of failing, letting + // the parser report a more precise error at the mismatch point - + // mirroring adaptivePredict's + // getAltThatFinishedDecisionEntryRule recovery. + int fallback = 0; + for (ATNConfig c : cs) { + if ((c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0 + && (fallback == 0 || c.alt < fallback)) { + fallback = c.alt; + } + } + fallbackAlts.set(d, fallback); + for (LabeledSuccessor ls : successors(configs, res)) { Integer id = stateIds.get(ls.configs); if (id == null) { @@ -354,6 +415,7 @@ else if (abortOnUntrustedConflict) { edges.add(new ArrayList()); edgeLabels.add(new ArrayList()); acceptAlts.add(0); + fallbackAlts.add(0); work.add(id); } edges.get(d).add(id); @@ -383,7 +445,7 @@ else if (abortOnUntrustedConflict) { if (res.category == Category.LLK || res.category == Category.LLSTAR || res.category == Category.EXACT_AMBIG) { - res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, cyclic, res.k); + res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, fallbackAlts, cyclic, res.k); } return false; } @@ -393,13 +455,16 @@ protected static StaticDFA toStaticDFA(int decision, List> edgeLabels, List> edgeTargets, List acceptAlts, + List fallbackAlts, boolean cyclic, int maxK) { int n = edgeTargets.size(); int[] accepts = new int[n]; + int[] fallbacks = new int[n]; int[] offsets = new int[n+1]; List triples = new ArrayList(); for (int s = 0; s < n; s++) { accepts[s] = acceptAlts.get(s); + fallbacks[s] = fallbackAlts.get(s); offsets[s] = triples.size()*3; List stateTriples = new ArrayList(); for (int e = 0; e < edgeTargets.get(s).size(); e++) { @@ -419,7 +484,7 @@ protected static StaticDFA toStaticDFA(int decision, edges[i*3+1] = triples.get(i)[1]; edges[i*3+2] = triples.get(i)[2]; } - return new StaticDFA(decision, n, accepts, offsets, edges, cyclic, maxK); + return new StaticDFA(decision, n, accepts, fallbacks, offsets, edges, cyclic, maxK); } /** A DFA edge under construction: token class label -> successor config set. */ @@ -562,9 +627,12 @@ protected void closure(ATNConfig config, Set configs, Set } return; } - // Wildcard context: keep the stop-state config (it participates in - // stop-state conflict detection and matches EOF), and additionally - // chase FOLLOW links via the epsilon transitions below. + // Wildcard context: popping through the decision-entry boundary. + // Taint the config (its descendants inherit through the copy + // constructors), keep it (it participates in stop-state conflict + // detection and matches EOF), and additionally chase FOLLOW + // links via the epsilon transitions below. + config.reachesIntoOuterContext |= BOUNDARY_TAINT; configs.add(config); } diff --git a/tool/src/org/antlr/v4/analysis/StaticDFA.java b/tool/src/org/antlr/v4/analysis/StaticDFA.java index fe37f898b9..6cf9281f91 100644 --- a/tool/src/org/antlr/v4/analysis/StaticDFA.java +++ b/tool/src/org/antlr/v4/analysis/StaticDFA.java @@ -31,6 +31,15 @@ public class StaticDFA { public final int numStates; /** Predicted alternative per state; 0 = not an accept state. */ public final int[] accepts; + /** + * Error-avoidance fallback per state; 0 = none. When prediction dies at + * a state on a token matching no edge, the walker returns this + * alternative (the minimum one that already finished the decision entry + * rule) instead of failing, so the parser reports a more precise error + * at the actual mismatch point - mirroring adaptivePredict's + * getAltThatFinishedDecisionEntryRule recovery. + */ + public final int[] fallbacks; /** Index of each state's first edge int in {@link #edges}; length numStates+1. */ public final int[] edgeOffsets; /** Flattened (lo, hi, target) triples, sorted by lo within each state. */ @@ -40,11 +49,12 @@ public class StaticDFA { /** Max lookahead depth if acyclic; -1 if cyclic. */ public final int maxK; - public StaticDFA(int decision, int numStates, int[] accepts, + public StaticDFA(int decision, int numStates, int[] accepts, int[] fallbacks, int[] edgeOffsets, int[] edges, boolean cyclic, int maxK) { this.decision = decision; this.numStates = numStates; this.accepts = accepts; + this.fallbacks = fallbacks; this.edgeOffsets = edgeOffsets; this.edges = edges; this.cyclic = cyclic; diff --git a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java index 8dba2829fd..a77639b3b8 100644 --- a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java +++ b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java @@ -34,12 +34,13 @@ * numStates * numEdgeInts * accepts[numStates] (predicted alt per state; 0 = non-accept) + * fallbacks[numStates] (error-avoidance alt per state; 0 = none) * edgeOffsets[numStates+1] (index of each state's first edge int) * edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) * */ public class SerializedStaticDFAs extends OutputModelObject { - public static final int FORMAT_VERSION = 2; + public static final int FORMAT_VERSION = 3; public final int numTables; /** Base64 text segments of the serialized blob, one rendered per line. */ @@ -77,6 +78,7 @@ public static void appendIntStream(Map dfas, data.add(dfa.numStates); data.add(dfa.edges.length); for (int v : dfa.accepts) data.add(v); + for (int v : dfa.fallbacks) data.add(v); for (int v : dfa.edgeOffsets) data.add(v); for (int v : dfa.edges) data.add(v); comments.add("decision "+dfa.decision+": " From 98b4d68e70c010e627f8bf6d491a8c609c9d58d2 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Thu, 9 Jul 2026 19:06:32 -0400 Subject: [PATCH 04/48] Add AGENTS.md: repo guide for the Rust-focused dbt-fusion fork Signed-off-by: Bo Lin --- AGENTS.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..7254b70231 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,93 @@ +# AGENTS.md + +## What this repo is + +This is **sdf-labs/antlr4** (`origin`), a **fork of antlr/antlr4** (`upstream`) maintained +for [dbt-fusion](https://github.com/dbt-labs/dbt-fusion). The fork's reason for existing is +the **Rust target**: the Rust runtime crate (`runtime/Rust`, published as `dbt-antlr4`) and +its tool codegen. Most upstream targets (Java, C++, Go, etc.) are inherited and rarely +touched here — nearly all fork work happens in `runtime/Rust` and the tool's Rust codegen. + +Two version numbers, kept in lockstep since 2.0.0 but set in different places: +- Tool/Java/Maven version: `pom.xml` `2.0.0` (the shaded tool jar is named + `dbt-antlr4--complete.jar` via `shadedArtifactId` in `tool/pom.xml`; + the Maven coordinate remains `org.antlr:antlr4`) +- Rust runtime crate version: `runtime/Rust/Cargo.toml` (`dbt-antlr4`, `2.0.0`) + + +## Build (Maven, builds the tool that generates parsers) + +ANTLR is written in itself, so the build has a self-dependency. Use `install`, not `compile`: + +```bash +export MAVEN_OPTS="-Xmx1G" # required on Linux +mvn install -DskipTests # produces tool/target/dbt-antlr4--complete.jar +``` + +Maven modules (`pom.xml`): `runtime/Java`, `tool`, `antlr4-maven-plugin`, `tool-testsuite`, +`runtime-testsuite`. JDK 21, Maven 3.8+. + +## Rust target: the important workflow + +The Rust runtime is a Cargo crate, **not** part of the Maven build. To work on it: + +```bash +cd runtime/Rust +cargo build +cargo test # runs tests against the checked-in generated parsers in tests/gen/ +``` + +Cargo features (off by default): `recursion-limit`, `arena-allocation-limit` — these gate +fork-specific safety limits added in recent commits. The `stacker` dep is optional. + +### Regenerating the Rust test parsers (critical, easy to get wrong) + +`runtime/Rust/tests/gen/` contains **checked-in generated parsers**. If you change the Rust +codegen template you must regenerate them, and this requires the freshly-built tool jar: + +```bash +# 1. build the tool jar first (from repo root): +mvn install -DskipTests +# 2. regenerate (script hardcodes TOOL_VERSION — update it if pom.xml version changed): +cd runtime/Rust && ./gen_test_grammars.sh +``` + +`gen_test_grammars.sh` has `TOOL_VERSION="2.0.0"` hardcoded and reads +`tool/target/dbt-antlr4-${TOOL_VERSION}-complete.jar`. Keep it in sync with `pom.xml`. + +### Single source of truth for the Rust codegen template + +`runtime/Rust/templates/Rust.stg` is a **symlink** to +`tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg`. Edit only the real file +under `tool/resources/...`; do not replace the symlink with a copy. + +Rust tool target Java class: `tool/src/org/antlr/v4/codegen/target/RustTarget.java`. + +## Runtime test suite (cross-target, JVM-driven) + +`runtime-testsuite` tests every target by launching processes to compile/run generated code. +Tests are defined as text descriptor files (not Java), see +`doc/antlr-project-testing.md`. Run a single target from the `runtime-testsuite` dir: + +```bash +cd runtime-testsuite +export MAVEN_OPTS="-Xmx1G" +mvn -Dtest='rust.**' test # or java.**, cpp.**, go.** ... +``` + +Rust runner lives at `runtime-testsuite/test/org/antlr/v4/test/runtime/rust/` and shells out +to `cargo`. Note: Rust is wired into `runtime-testsuite` but is **not** in the CI matrix in +`.github/workflows/hosted.yml` — CI does not test Rust, so verify Rust changes locally. + +Two Rust suites exist: `rust.RustRuntimeTests` (adaptive prediction, all descriptors) and +`rust.RustStaticDFARuntimeTests` (same corpus generated with `-Xstatic-dfa`; a differential +test of table-driven static prediction — skips `showDiagnosticErrors`/`traceATN` descriptors, +which introspect the adaptive engine that static tables bypass). + +Tool-only unit tests: `cd tool-testsuite && mvn test`. + +## Conventions + +- Commits require DCO sign-off: `git commit -s` (lowercase `-s`). See `CONTRIBUTING.md`. +- `.editorconfig` defines the Java style; `runtime/Rust/rustfmt.toml` (edition 2021) the Rust style. +- Contributor conduct rules: `ANTLR-HOUSE-RULES.md`. From a6cb1229746413ea669fa1a2e000f72fecadc4f5 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 11 Jul 2026 10:53:09 -0400 Subject: [PATCH 05/48] Per-precedence static DFA tables for left-recursive loop decisions The operator loop decision of a left-recursive rule (the StarLoopEntryState the LR transformer generates) cannot be served by a single static DFA because its behavior depends on the current precedence: each operator alternative is guarded by precpred(_ctx, n), which holds iff n >= _p. The adaptive runtime handles this by keeping a separate lazily-built DFA start state per precedence value (DFA.isPrecedenceDfa). Statically, the guard constants n1<...=0 (plain table index), -1 (no table), -(dispatch offset)-2 (precedence-dispatched). Class dispatch: class(p) = #cutoffs < p, a linear scan over <= a handful of entries. Runtimes (Rust static_dfa.rs + Java StaticDFATables): both walkers fetch parser.get_precedence() once at dfa_predict entry and resolve the table via the dispatch; plain decisions ignore the precedence. Zero template changes - the LR loop is a StarBlock selected as DFAStarBlock by the existing hasStaticDFA gate, now extended to recognize precedence groups. Tests: new runtime/Rust/grammars/LrDfa.g4 exercises every shape that makes precedence prediction hard - multiple binary precedence levels, right-associative operators (^ and ternary), a prefix operator, a postfix operator, and array indexing (e '[' e ']', whose nested 0-precedence re-entry exercises the suppression path). Generated with -Xstatic-dfa; the operator loop is fully table-driven (zero adaptive_predict call sites) with per-precedence class dispatch. 9 Rust unit tests cover associativity, suppression, ternary, mixed expressions, and error recovery. Verified: both Rust runtime suites 707/707 (the LeftRecursion/* descriptors now run through the dispatch), tool-testsuite 694, Java differential probe 29/29 against an adaptive-prediction build of the same grammar including malformed inputs, p1probe v3-era regression 24/24 under v4, full cargo test + fmt clean. Effect on SQL grammars: 10 of 34 LR loop decisions go static (those whose SLL prediction is context-independent per class). The remaining 24 demote with approx[{1,2}] conflicts that are genuinely context- sensitive - isolated to inputs like 'FRAME BETWEEN b AND b' where AND cannot be resolved without the real stack (BETWEEN separator vs boolean operator). The classifier demotes precisely the decisions that are theoretically non-static; the adaptive runtime pays a full-context LL retry on every such token, which no SLL table can precompute. Signed-off-by: Bo Lin --- .../Java/src/org/antlr/v4/runtime/Parser.java | 9 +- .../antlr/v4/runtime/atn/StaticDFATables.java | 74 +- runtime/Rust/gen_test_grammars.sh | 2 + runtime/Rust/grammars/LrDfa.g4 | 18 + runtime/Rust/src/parser.rs | 9 +- runtime/Rust/src/static_dfa.rs | 69 +- runtime/Rust/tests/gen/lrdfabaselistener.rs | 131 ++ runtime/Rust/tests/gen/lrdfalexer.rs | 138 ++ runtime/Rust/tests/gen/lrdfalistener.rs | 110 ++ runtime/Rust/tests/gen/lrdfaparser.rs | 1535 +++++++++++++++++ runtime/Rust/tests/gen/staticdfaparser.rs | 4 +- runtime/Rust/tests/lr_dfa_tests.rs | 165 ++ tool/src/org/antlr/v4/Tool.java | 2 +- .../antlr/v4/analysis/DecisionClassifier.java | 353 +++- .../v4/analysis/PrecedenceStaticDFA.java | 46 + .../org/antlr/v4/codegen/ParserFactory.java | 6 +- .../org/antlr/v4/codegen/model/Parser.java | 7 +- .../v4/codegen/model/SerializedBase64ATN.java | 12 +- .../codegen/model/SerializedStaticDFAs.java | 114 +- tool/src/org/antlr/v4/tool/Grammar.java | 8 + 20 files changed, 2730 insertions(+), 82 deletions(-) create mode 100644 runtime/Rust/grammars/LrDfa.g4 create mode 100644 runtime/Rust/tests/gen/lrdfabaselistener.rs create mode 100644 runtime/Rust/tests/gen/lrdfalexer.rs create mode 100644 runtime/Rust/tests/gen/lrdfalistener.rs create mode 100644 runtime/Rust/tests/gen/lrdfaparser.rs create mode 100644 runtime/Rust/tests/lr_dfa_tests.rs create mode 100644 tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java index 1b41e0ce02..d484d4c384 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java @@ -546,19 +546,22 @@ public Token getCurrentToken() { public int dfaPredict(StaticDFATables tables, int decision) throws RecognitionException { + // the precedence selects the table of dispatched decisions (the + // operator loops of left-recursive rules); plain decisions ignore it + int table = tables.tableFor(decision, getPrecedence()); int s = 0; int i = 1; while (true) { - int alt = tables.accept(decision, s); + int alt = tables.accept(table, s); if ( alt>0 ) return alt; - int next = tables.edge(decision, s, _input.LA(i)); + int next = tables.edge(table, s, _input.LA(i)); if ( next<0 ) { // No viable transition. If some alternative already finished // the decision entry rule, predict it and let the parser // report a more precise error at the actual mismatch point - // mirroring adaptivePredict's recovery via // getAltThatFinishedDecisionEntryRule. - int fallback = tables.fallback(decision, s); + int fallback = tables.fallback(table, s); if ( fallback>0 ) return fallback; throw new NoViableAltException(this, _input, _input.LT(1), _input.LT(i), diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java index 1237cbe924..e107ce918e 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java @@ -27,13 +27,19 @@ * numTables * numDecisionSlots (max decision number + 1) * for each table: - * decision + * decision (-1: referenced only via a dispatch below) * numStates * numEdgeInts * accepts[numStates] (predicted alt per state; 0 = non-accept) * fallbacks[numStates] (error-avoidance alt per state; 0 = none) * edgeOffsets[numStates+1] (index of each state's first edge int) * edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) + * numPrecedenceDispatches + * for each dispatch: (a left-recursive precedence loop decision) + * decision + * numCutoffs + * cutoffs[numCutoffs] (sorted; class(p) = #cutoffs < p) + * tableIndex[numCutoffs+1] (table of each precedence class) * * *

State 0 of each table is its start state; {@code accepts[s] > 0} marks @@ -42,22 +48,37 @@ * edge means no viable alternative. Cyclic tables (LL(*) decisions) are * walked by the same loop; termination is guaranteed because every step * consumes one token of lookahead and the input is finite.

+ * + *

Precedence dispatches serve the operator loops of left-recursive + * rules: the loop's viable-operator set depends on the current precedence + * (the {@code _p} argument of the rewritten rule), so the tool precomputes + * one table per precedence equivalence class and the walker selects by + * {@code getPrecedence()} - the static analogue of the adaptive runtime's + * per-precedence DFA start states.

*/ public class StaticDFATables { /** Must match the tool's SerializedStaticDFAs.FORMAT_VERSION. */ - public static final int FORMAT_VERSION = 3; + public static final int FORMAT_VERSION = 4; /** Concatenated per-table data: accepts, fallbacks, edgeOffsets, edges. */ protected final int[] data; /** Per-table (acceptsAt, fallbacksAt, edgeOffsetsAt, edgesAt, endAt) indexes into {@link #data}. */ protected final int[] metas; - /** decision number -> table index, or -1. */ + /** + * decision number -> table index ({@code >= 0}), -1 (no table), or + * {@code -(dispatch offset) - 2}: an offset into {@link #dispatchData}, + * where a dispatch entry reads {@code numCutoffs, cutoffs..., + * tableIndex...} ({@code numCutoffs+1} table indices). + */ protected final int[] decisionToTable; + /** Flattened precedence dispatch entries. */ + protected final int[] dispatchData; - protected StaticDFATables(int[] data, int[] metas, int[] decisionToTable) { + protected StaticDFATables(int[] data, int[] metas, int[] decisionToTable, int[] dispatchData) { this.data = data; this.metas = metas; this.decisionToTable = decisionToTable; + this.dispatchData = dispatchData; } /** @@ -91,7 +112,7 @@ public static StaticDFATables deserialize(String[] segments) { int decision = ints.next(); int numStates = ints.next(); int numEdgeInts = ints.next(); - decisionToTable[decision] = table; + if (decision >= 0) decisionToTable[decision] = table; metas[table*5] = data.size; // acceptsAt for (int i = 0; i < numStates; i++) data.add(ints.next()); @@ -103,15 +124,43 @@ public static StaticDFATables deserialize(String[] segments) { for (int i = 0; i < numEdgeInts; i++) data.add(ints.next()); metas[table*5+4] = data.size; // endAt } + int numDispatches = ints.next(); + IntBuffer dispatchData = new IntBuffer(); + for (int dispatch = 0; dispatch < numDispatches; dispatch++) { + int decision = ints.next(); + decisionToTable[decision] = -dispatchData.size - 2; + int numCutoffs = ints.next(); + dispatchData.add(numCutoffs); + for (int i = 0; i < 2*numCutoffs + 1; i++) dispatchData.add(ints.next()); + } if (!ints.atEnd()) { throw new IllegalStateException("trailing bytes in static DFA blob"); } - return new StaticDFATables(data.toArray(), metas, decisionToTable); + return new StaticDFATables(data.toArray(), metas, decisionToTable, dispatchData.toArray()); } - /** Predicted alternative if {@code state} of {@code decision}'s table accepts; else 0. */ - public int accept(int decision, int state) { - int acceptsAt = metas[decisionToTable[decision]*5]; + /** + * The table serving {@code decision}: {@code precedence} (the parser's + * current precedence, i.e. the top of its precedence stack) selects the + * precedence class of dispatched decisions - the operator loops of + * left-recursive rules - and is ignored for plain ones. + */ + public int tableFor(int decision, int precedence) { + int table = decisionToTable[decision]; + if (table <= -2) { + // precedence dispatch: class(p) = #cutoffs < p + int at = -table - 2; + int numCutoffs = dispatchData[at]; + int cls = 0; + while (cls < numCutoffs && dispatchData[at+1+cls] < precedence) cls++; + table = dispatchData[at+1+numCutoffs+cls]; + } + return table; + } + + /** Predicted alternative if {@code state} of {@code table} accepts; else 0. */ + public int accept(int table, int state) { + int acceptsAt = metas[table*5]; return data[acceptsAt+state]; } @@ -122,14 +171,13 @@ public int accept(int decision, int state) { * error at the actual mismatch point (mirroring adaptivePredict's * getAltThatFinishedDecisionEntryRule recovery). */ - public int fallback(int decision, int state) { - int fallbacksAt = metas[decisionToTable[decision]*5+1]; + public int fallback(int table, int state) { + int fallbacksAt = metas[table*5+1]; return data[fallbacksAt+state]; } /** Successor of {@code state} on token {@code t}, or -1 (binary search). */ - public int edge(int decision, int state, int t) { - int table = decisionToTable[decision]; + public int edge(int table, int state, int t) { int edgeOffsetsAt = metas[table*5+2]; int edgesAt = metas[table*5+3]; int lo = data[edgeOffsetsAt+state]/3; diff --git a/runtime/Rust/gen_test_grammars.sh b/runtime/Rust/gen_test_grammars.sh index 1cd455637f..4e4494ef37 100755 --- a/runtime/Rust/gen_test_grammars.sh +++ b/runtime/Rust/gen_test_grammars.sh @@ -14,6 +14,7 @@ declare -a GRAMMARS=( "SimpleLR" "Labels" "StaticDFA" + "LrDfa" # "FHIRPath" ) @@ -26,6 +27,7 @@ declare -a ADDITIONAL_ARGS=( "" "" "-Xstatic-dfa" + "-Xstatic-dfa" ) for i in "${!GRAMMARS[@]}"; do diff --git a/runtime/Rust/grammars/LrDfa.g4 b/runtime/Rust/grammars/LrDfa.g4 new file mode 100644 index 0000000000..032bc7fc7c --- /dev/null +++ b/runtime/Rust/grammars/LrDfa.g4 @@ -0,0 +1,18 @@ +grammar LrDfa; + +s : e EOF ; + +e : e '[' e ']' # Index + | e '!' # Fact + | '-' e # Neg + | e '^' e # Pow + | e ('*'|'/') e # Mul + | e ('+'|'-') e # Add + | e '?' e ':' e # Ternary + | ID # Id + | INT # Int + ; + +ID : [a-z]+ ; +INT : [0-9]+ ; +WS : [ \t\r\n]+ -> skip ; diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 13e2a2766f..764a549672 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -480,7 +480,14 @@ where /// matching no table edge produces a `NoViableAlt` error anchored at the /// decision start token, matching `adaptive_predict`'s convention. pub fn dfa_predict(&mut self, decision: i32) -> Result { - let dfa = self.atn_manager.atn().static_dfas.table(decision); + // the precedence selects the table of dispatched decisions (the + // operator loops of left-recursive rules); plain decisions ignore it + let precedence = self.get_precedence(); + let dfa = self + .atn_manager + .atn() + .static_dfas + .table(decision, precedence); let mut s = 0usize; let mut i = 1isize; loop { diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs index 4c95fcbb18..ec3d740ff8 100644 --- a/runtime/Rust/src/static_dfa.rs +++ b/runtime/Rust/src/static_dfa.rs @@ -21,18 +21,32 @@ //! numTables //! numDecisionSlots (max decision number + 1) //! for each table: -//! decision +//! decision (-1: referenced only via a dispatch below) //! numStates //! numEdgeInts //! accepts[numStates] (predicted alt per state; 0 = non-accept) //! fallbacks[numStates] (error-avoidance alt per state; 0 = none) //! edgeOffsets[numStates+1] (index of each state's first edge i32) //! edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) +//! numPrecedenceDispatches +//! for each dispatch: (a left-recursive precedence loop decision) +//! decision +//! numCutoffs +//! cutoffs[numCutoffs] (sorted; class(p) = #cutoffs < p) +//! tableIndex[numCutoffs+1] (table of each precedence class) //! ``` +//! +//! Precedence dispatches serve the operator loops of left-recursive rules: +//! the loop's viable-operator set depends on the current precedence (the +//! `_p` argument of the rewritten rule), so one table per precedence +//! equivalence class is precomputed and the walker selects by +//! `get_precedence()` - the static analogue of the adaptive runtime's +//! per-precedence DFA start states, and the reason the generated loop +//! behaves like a hand-rolled precedence-climbing (Pratt) parser. /// Format version understood by this runtime; must match the tool's /// `SerializedStaticDFAs.FORMAT_VERSION`. -pub const FORMAT_VERSION: i32 = 3; +pub const FORMAT_VERSION: i32 = 4; /// The deserialized static prediction tables of one generated parser. /// @@ -51,8 +65,14 @@ pub struct StaticDFATables { data: Vec, /// Per-table (accepts_at, fallbacks_at, edge_offsets_at, edges_at) indexes into `data`. metas: Vec<(usize, usize, usize, usize)>, - /// decision number -> table index, or -1. + /// decision number -> table index (`>= 0`), `-1` (no table), or + /// `-(dispatch index) - 2` (precedence-dispatched decision). decision_to_table: Vec, + /// Flattened dispatch entries: `numCutoffs, cutoffs..., tableIndex...` + /// (`numCutoffs + 1` table indices). + dispatch_data: Vec, + /// Per-dispatch start offset into `dispatch_data`. + dispatch_at: Vec, } /// Borrowed view of one decision's table. @@ -80,6 +100,8 @@ impl StaticDFATables { data: Vec::new(), metas: Vec::new(), decision_to_table: Vec::new(), + dispatch_data: Vec::new(), + dispatch_at: Vec::new(), } } @@ -108,10 +130,12 @@ impl StaticDFATables { let mut decision_to_table = vec![-1i32; num_slots]; for table in 0..num_tables { - let decision = next() as usize; + let decision = next(); let num_states = next() as usize; let num_edge_ints = next() as usize; - decision_to_table[decision] = table as i32; + if decision >= 0 { + decision_to_table[decision as usize] = table as i32; + } let accepts_at = data.len(); for _ in 0..num_states { @@ -131,6 +155,20 @@ impl StaticDFATables { } metas.push((accepts_at, fallbacks_at, edge_offsets_at, edges_at)); } + + let num_dispatches = next() as usize; + let mut dispatch_data = Vec::new(); + let mut dispatch_at = Vec::with_capacity(num_dispatches); + for dispatch in 0..num_dispatches { + let decision = next() as usize; + decision_to_table[decision] = -(dispatch as i32) - 2; + dispatch_at.push(dispatch_data.len()); + let num_cutoffs = next() as usize; + dispatch_data.push(num_cutoffs as i32); + for _ in 0..2 * num_cutoffs + 1 { + dispatch_data.push(next()); + } + } drop(next); assert!(ints.next().is_none(), "trailing data in static DFA blob"); @@ -138,14 +176,27 @@ impl StaticDFATables { data, metas, decision_to_table, + dispatch_data, + dispatch_at, } } - /// The table for a decision; panics if the decision has no static table - /// (generated code only references decisions it has tables for). + /// The table for a decision; `precedence` (the parser's current + /// precedence, i.e. the top of its precedence stack) selects the + /// precedence class of dispatched decisions and is ignored for plain + /// ones. Panics if the decision has no static table (generated code + /// only references decisions it has tables for). #[inline] - pub fn table(&self, decision: i32) -> StaticDFATable<'_> { - let t = self.decision_to_table[decision as usize]; + pub fn table(&self, decision: i32, precedence: i32) -> StaticDFATable<'_> { + let mut t = self.decision_to_table[decision as usize]; + if t <= -2 { + // precedence dispatch: class(p) = #cutoffs < p + let at = self.dispatch_at[(-t - 2) as usize]; + let num_cutoffs = self.dispatch_data[at] as usize; + let cutoffs = &self.dispatch_data[at + 1..at + 1 + num_cutoffs]; + let class = cutoffs.iter().take_while(|&&c| c < precedence).count(); + t = self.dispatch_data[at + 1 + num_cutoffs + class]; + } assert!(t >= 0, "no static DFA table for decision {}", decision); let (accepts_at, fallbacks_at, edge_offsets_at, edges_at) = self.metas[t as usize]; let end = self diff --git a/runtime/Rust/tests/gen/lrdfabaselistener.rs b/runtime/Rust/tests/gen/lrdfabaselistener.rs new file mode 100644 index 0000000000..cf537eb968 --- /dev/null +++ b/runtime/Rust/tests/gen/lrdfabaselistener.rs @@ -0,0 +1,131 @@ +// Generated from LrDfa.g4 by ANTLR 4.13.2 + +use super::lrdfaparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by LrDfaParser. + +pub trait LrDfaBaseListener<'arena>: + ParseTreeListener<'arena, LrDfaParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_add(&mut self, _ctx: &AddContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_add(&mut self, _ctx: &AddContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_neg(&mut self, _ctx: &NegContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_neg(&mut self, _ctx: &NegContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_mul(&mut self, _ctx: &MulContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_mul(&mut self, _ctx: &MulContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_ternary(&mut self, _ctx: &TernaryContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_ternary(&mut self, _ctx: &TernaryContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_pow(&mut self, _ctx: &PowContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_pow(&mut self, _ctx: &PowContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_index(&mut self, _ctx: &IndexContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_index(&mut self, _ctx: &IndexContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_id(&mut self, _ctx: &IdContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_id(&mut self, _ctx: &IdContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_fact(&mut self, _ctx: &FactContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_fact(&mut self, _ctx: &FactContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_int(&mut self, _ctx: &IntContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link LrDfaBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_int(&mut self, _ctx: &IntContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/lrdfalexer.rs b/runtime/Rust/tests/gen/lrdfalexer.rs new file mode 100644 index 0000000000..dc1bf43b7e --- /dev/null +++ b/runtime/Rust/tests/gen/lrdfalexer.rs @@ -0,0 +1,138 @@ +// Generated from LrDfa.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const T__8:i32=9; +pub const T__9:i32=10; +pub const ID:i32=11; +pub const INT:i32=12; +pub const WS:i32=13; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;13] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "ID", "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;11] = [ + None, Some("'['"), Some("']'"), Some("'!'"), Some("'-'"), Some("'^'"), + Some("'*'"), Some("'/'"), Some("'+'"), Some("'?'"), Some("':'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;14] = [ + None, None, None, None, None, None, None, None, None, None, None, Some("ID"), + Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, LrDfaLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct LrDfaLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { LrDfaLexer } +dbt_antlr4::impl_deref! { lexer => LrDfaLexer } + +impl<'input, 'arena, Input, TF> LrDfaLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = LrDfaLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct LrDfaLexerActions { +} + +impl LrDfaLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for LrDfaLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for LrDfaLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "LrDfaLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 10] = [ + "CAAagAEMAQQADgAEAg4CBAQOBAQGDgYECA4IBAoOCgQMDgwEDg4OBBAOEAQSDhIEFA4UBBYOFgQYDhgC", + "AAIAAgICAgIEAgQCBgIGAggCCAIKAgoCDAIMAg4CDgIQAhACEgISAhQIFGIQFBYUGBRkAhYIFmwQFhYW", + "GBZuAhgIGHYQGBYYGBh4AhgCGAAAGgICBgQKBg4IEgoWDBoOHhAiEiYUKhYuGDIaAgAGAgDCAfQBAgBg", + "cgYAEhQaGkBAhAEAAgIAAAAABgIAAAAACgIAAAAADgIAAAAAEgIAAAAAFgIAAAAAGgIAAAAAHgIAAAAA", + "IgIAAAAAJgIAAAAAKgIAAAAALgIAAAAAMgIAAAACNgIAAAAGOgIAAAAKPgIAAAAOQgIAAAASRgIAAAAW", + "SgIAAAAaTgIAAAAeUgIAAAAiVgIAAAAmWgIAAAAqYAIAAAAuagIAAAAydAIAAAA2OAq2AQAAOAQCAAAA", + "OjwKugEAADwIAgAAAD5ACkIAAEAMAgAAAEJECloAAEQQAgAAAEZICrwBAABIFAIAAABKTApUAABMGAIA", + "AABOUApeAABQHAIAAABSVApWAABUIAIAAABWWAp+AABYJAIAAABaXAp0AABcKAIAAABeYg4AAABgXgIA", + "AABiZAIAAABkYAIAAABkZgIAAABmLAIAAABobA4CAABqaAIAAABsbgIAAABuagIAAABucAIAAABwMAIA", + "AABydg4EAAB0cgIAAAB2eAIAAAB4dAIAAAB4egIAAAB6fAIAAAB8fgwYAAB+NAIAAAAIAGRueAIMAAA=" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/lrdfalistener.rs b/runtime/Rust/tests/gen/lrdfalistener.rs new file mode 100644 index 0000000000..59d89670ee --- /dev/null +++ b/runtime/Rust/tests/gen/lrdfalistener.rs @@ -0,0 +1,110 @@ +#![allow(nonstandard_style)] +// Generated from LrDfa.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::lrdfaparser::*; + +pub trait LrDfaListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, LrDfaParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link LrDfaParser#s}. + /// @param ctx the parse tree + fn enter_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link LrDfaParser#s}. + /// @param ctx the parse tree + fn exit_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Add} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Add<'input: 'arena>(&mut self, _ctx: &AddContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Add} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Add<'input: 'arena>(&mut self, _ctx: &AddContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Neg} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Neg<'input: 'arena>(&mut self, _ctx: &NegContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Neg} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Neg<'input: 'arena>(&mut self, _ctx: &NegContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Mul} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Mul<'input: 'arena>(&mut self, _ctx: &MulContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Mul} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Mul<'input: 'arena>(&mut self, _ctx: &MulContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Ternary} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Ternary<'input: 'arena>(&mut self, _ctx: &TernaryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Ternary} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Ternary<'input: 'arena>(&mut self, _ctx: &TernaryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Pow} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Pow<'input: 'arena>(&mut self, _ctx: &PowContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Pow} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Pow<'input: 'arena>(&mut self, _ctx: &PowContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Index} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Index<'input: 'arena>(&mut self, _ctx: &IndexContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Index} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Index<'input: 'arena>(&mut self, _ctx: &IndexContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Id} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Id<'input: 'arena>(&mut self, _ctx: &IdContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Id} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Id<'input: 'arena>(&mut self, _ctx: &IdContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Fact} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Fact<'input: 'arena>(&mut self, _ctx: &FactContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Fact} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Fact<'input: 'arena>(&mut self, _ctx: &FactContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code Int} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn enter_Int<'input: 'arena>(&mut self, _ctx: &IntContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code Int} + /// labeled alternative in {@link LrDfaParser#e}. + /// @param ctx the parse tree + fn exit_Int<'input: 'arena>(&mut self, _ctx: &IntContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/lrdfaparser.rs b/runtime/Rust/tests/gen/lrdfaparser.rs new file mode 100644 index 0000000000..b1a2266283 --- /dev/null +++ b/runtime/Rust/tests/gen/lrdfaparser.rs @@ -0,0 +1,1535 @@ +// Generated from LrDfa.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::lrdfalistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const LrDfa_T__0:i32=1; +pub const LrDfa_T__1:i32=2; +pub const LrDfa_T__2:i32=3; +pub const LrDfa_T__3:i32=4; +pub const LrDfa_T__4:i32=5; +pub const LrDfa_T__5:i32=6; +pub const LrDfa_T__6:i32=7; +pub const LrDfa_T__7:i32=8; +pub const LrDfa_T__8:i32=9; +pub const LrDfa_T__9:i32=10; +pub const LrDfa_ID:i32=11; +pub const LrDfa_INT:i32=12; +pub const LrDfa_WS:i32=13; +pub const LrDfa_EOF:i32=EOF; +pub const RULE_s:usize = 0; +pub const RULE_e:usize = 1; +pub const ruleNames: [&'static str; 2] = [ + "s", "e" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;11] = [ + None, Some("'['"), Some("']'"), Some("'!'"), Some("'-'"), Some("'^'"), + Some("'*'"), Some("'/'"), Some("'+'"), Some("'?'"), Some("':'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;14] = [ + None, None, None, None, None, None, None, None, None, None, None, Some("ID"), + Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, LrDfaParserExt<'input, 'arena>, LrDfaParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct LrDfaParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> LrDfaParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + LrDfaParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: LrDfaListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct LrDfaTreeWalker; +impl LrDfaTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: LrDfaListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, LrDfaParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum LrDfaParserNodeKind { + SContext, + EContext, + Terminal, + Error, +} +pub type LrDfaParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, LrDfaParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => LrDfaParser } +dbt_antlr4::impl_node_kind! { LrDfaParserNodeKind { + EContext(EContextAll), ; SContext(enter_s, exit_s, ), + }; listener = dyn LrDfaListener<'arena, Tok>, +} + +pub struct LrDfaParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> LrDfaParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for LrDfaParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for LrDfaParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "LrDfa.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena LrDfaParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 1 => LrDfaParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> LrDfaParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn e_sempred(_ctx: Option<&'arena EContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 6) + } + 1 => { + recog.precpred(None, 5) + } + 2 => { + recog.precpred(None, 4) + } + 3 => { + recog.precpred(None, 3) + } + 4 => { + recog.precpred(None, 9) + } + 5 => { + recog.precpred(None, 8) + } + _ => true + } + } +} +//------------------- s ---------------- +pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; + +pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; +#[derive(Debug)] +pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::SContext } + fn get_rule_index(&self) -> usize { RULE_s } + fn make_node( + arena: &'arena Arena, + ctx: SContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena LrDfaParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut LrDfaParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { + ph: PhantomData + } + ) + } +} + +pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> SContextAttrs<'input, 'arena, Tok> for SContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == LrDfa_EOF) + } +} + +impl<'input, 'arena, Input, TF> LrDfaParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(4); + recog.e_rec(0)?; + recog.base.set_state(5); + recog.base.match_token(LrDfa_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- e ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum EContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + AddContext(AddContext<'input, 'arena, Tok>), + NegContext(NegContext<'input, 'arena, Tok>), + MulContext(MulContext<'input, 'arena, Tok>), + TernaryContext(TernaryContext<'input, 'arena, Tok>), + PowContext(PowContext<'input, 'arena, Tok>), + IndexContext(IndexContext<'input, 'arena, Tok>), + IdContext(IdContext<'input, 'arena, Tok>), + FactContext(FactContext<'input, 'arena, Tok>), + IntContext(IntContext<'input, 'arena, Tok>), + Error(EContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { EContextAll { } { AddContext, NegContext, MulContext, TernaryContext, PowContext, IndexContext, IdContext, FactContext, IntContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { EContextAll { } { AddContext, NegContext, MulContext, TernaryContext, PowContext, IndexContext, IdContext, FactContext, IntContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { LrDfaParserNodeKind::EContextAll { AddContext, NegContext, MulContext, TernaryContext, PowContext, IndexContext, IdContext, FactContext, IntContext, Error, } } +dbt_antlr4::impl_node_inner! { LrDfaParserNodeKind::EContext::EContextAll { AddContext, NegContext, MulContext, TernaryContext, PowContext, IndexContext, IdContext, FactContext, IntContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { LrDfaListener::LrDfaParserNodeKind::EContextAll { AddContext(enter_Add, exit_Add), NegContext(enter_Neg, exit_Neg), MulContext(enter_Mul, exit_Mul), TernaryContext(enter_Ternary, exit_Ternary), PowContext(enter_Pow, exit_Pow), IndexContext(enter_Index, exit_Index), IdContext(enter_Id, exit_Id), FactContext(enter_Fact, exit_Fact), IntContext(enter_Int, exit_Int), } } + +impl<'input, 'arena, Tok> Deref for EContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn EContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use EContextAll::*; + match self{ + AddContext(inner) => inner, + NegContext(inner) => inner, + MulContext(inner) => inner, + TernaryContext(inner) => inner, + PowContext(inner) => inner, + IndexContext(inner) => inner, + IdContext(inner) => inner, + FactContext(inner) => inner, + IntContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type EContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; +#[derive(Debug)] +pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: EContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena LrDfaParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut LrDfaParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, EContextExt { + ph: PhantomData + } + ) + } +} + +pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> EContextAttrs<'input, 'arena, Tok> for EContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type AddContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AddContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait AddContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AddContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AddContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: AddContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::AddContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AddContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::AddContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AddContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::AddContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::AddContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type NegContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NegContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait NegContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NegContextAttrs<'input, 'arena, Tok> for NegContext<'input, 'arena, Tok> +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct NegContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NegContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: NegContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::NegContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NegContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::NegContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NegContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::NegContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for NegContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NegContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::NegContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type MulContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, MulContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait MulContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct MulContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for MulContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: MulContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::MulContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a MulContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::MulContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut MulContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::MulContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::MulContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type TernaryContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, TernaryContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait TernaryContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> TernaryContextAttrs<'input, 'arena, Tok> for TernaryContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct TernaryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for TernaryContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: TernaryContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::TernaryContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a TernaryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::TernaryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut TernaryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::TernaryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for TernaryContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> TernaryContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::TernaryContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type PowContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PowContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait PowContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PowContextAttrs<'input, 'arena, Tok> for PowContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct PowContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PowContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: PowContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::PowContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PowContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::PowContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PowContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::PowContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for PowContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PowContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::PowContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type IndexContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, IndexContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait IndexContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> IndexContextAttrs<'input, 'arena, Tok> for IndexContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct IndexContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for IndexContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: IndexContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::IndexContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a IndexContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::IndexContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut IndexContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::IndexContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for IndexContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> IndexContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::IndexContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type IdContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, IdContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait IdContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> IdContextAttrs<'input, 'arena, Tok> for IdContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == LrDfa_ID) + } +} +#[derive(Debug)] +pub struct IdContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for IdContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: IdContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::IdContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a IdContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::IdContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut IdContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::IdContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for IdContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> IdContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::IdContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type FactContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, FactContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait FactContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> FactContextAttrs<'input, 'arena, Tok> for FactContext<'input, 'arena, Tok> +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct FactContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for FactContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: FactContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::FactContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a FactContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::FactContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut FactContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::FactContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for FactContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> FactContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::FactContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type IntContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, IntContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; + +pub trait IntContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> IntContextAttrs<'input, 'arena, Tok> for IntContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == LrDfa_INT) + } +} +#[derive(Debug)] +pub struct IntContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for IntContextExt<'input, 'arena, Tok> +{ + type NodeKind = LrDfaParserNodeKind; + fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: IntContext<'input, 'arena, Tok>, + ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::IntContext(ctx)) + } + fn cast_from<'a>( + node: &'a LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a IntContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::IntContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut IntContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::IntContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for IntContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> IntContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut LrDfaParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::IntContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> LrDfaParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.e_rec(0) + } + + fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 2; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(12); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + LrDfa_T__3 => { + { + recog.base.with_mut_ctx(|ctx| { NegContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NegContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(8); + recog.base.match_token(LrDfa_T__3,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(9); + recog.e_rec(7)?; + }} + LrDfa_ID => { + { + recog.base.with_mut_ctx(|ctx| { IdContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena IdContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(10); + recog.base.match_token(LrDfa_ID,&mut recog.err_handler)?; + }} + LrDfa_INT => { + { + recog.base.with_mut_ctx(|ctx| { IntContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena IntContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(11); + recog.base.match_token(LrDfa_INT,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(38); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.base.dfa_predict(2)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(36); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.dfa_predict(1)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + PowContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena PowContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(14); + if !({recog.precpred(None, 6)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; + } + recog.base.set_state(15); + recog.base.match_token(LrDfa_T__4,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(16); + recog.e_rec(6)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + MulContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(17); + if !({recog.precpred(None, 5)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 5)".to_owned()), None))?; + } + recog.base.set_state(18); + _la = recog.base.input.la(1); + if { !(_la==LrDfa_T__5 || _la==LrDfa_T__6) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(19); + recog.e_rec(6)?; + } + } + , + 3 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AddContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(20); + if !({recog.precpred(None, 4)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; + } + recog.base.set_state(21); + _la = recog.base.input.la(1); + if { !(_la==LrDfa_T__3 || _la==LrDfa_T__7) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(22); + recog.e_rec(5)?; + } + } + , + 4 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + TernaryContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena TernaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(23); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(24); + recog.base.match_token(LrDfa_T__8,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(25); + recog.e_rec(0)?; + recog.base.set_state(26); + recog.base.match_token(LrDfa_T__9,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(27); + recog.e_rec(3)?; + } + } + , + 5 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + IndexContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena IndexContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(29); + if !({recog.precpred(None, 9)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 9)".to_owned()), None))?; + } + recog.base.set_state(30); + recog.base.match_token(LrDfa_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(31); + recog.e_rec(0)?; + recog.base.set_state(32); + recog.base.match_token(LrDfa_T__1,&mut recog.err_handler)?; + } + } + , + 6 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + FactContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena FactContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(34); + if !({recog.precpred(None, 8)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 8)".to_owned()), None))?; + } + recog.base.set_state(35); + recog.base.match_token(LrDfa_T__2,&mut recog.err_handler)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(40); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.base.dfa_predict(2)?; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} + +// the serialized ATN is followed by 8 static SLL prediction tables (-Xstatic-dfa): +// decision 2: precedence-dispatched over cutoffs [3, 4, 5, 6, 8, 9], tables [1 2 3 4 5 6 7] +// decision 1: LL(k), k=1, 7 states +// table 1 (decision 2): LL(k), k=1, 8 states +// table 2 (decision 2): LL(k), k=1, 8 states +// table 3 (decision 2): LL(k), k=1, 9 states +// table 4 (decision 2): LL(k), k=1, 9 states +// table 5 (decision 2): LL(k), k=1, 8 states +// table 6 (decision 2): LL(k), k=1, 7 states +// table 7 (decision 2): LL(k), k=0, 1 states +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 13] = [ + "CAIaVAQADgAEAg4CAgACAAIAAgICAgICAgICAgYCGhACAgICAgICAgICAgICAgICAgICAgICAgICAgIC", + "AgICAgICAgICAgICAgICAgIKAkoQAhQCGAJQEgICAgACBAQABAAEAgAMDgQACAgQEF4ACAIAAAAEGAIA", + "AAAICgYEAgAKDAoAAAIMAgIAAAAOEAwCAQAQEgoIAAASGgYEAg4UGgoWAAAWGgoYAAAYDgIAAAAYFAIA", + "AAAYFgIAAAAaTAIAAAAcHhQMAAAeIAoKAAAgSgYEAgwiJBQKAAAkJg4AAAAmSgYEAgwoKhQIAAAqLA4C", + "AAAsSgYEAgouMBQGAAAwMgoSAAAyNAYEAgA0NgoUAAA2OAYEAgY4SgIAAAA6PBQSAAA8PgoCAAA+QAYE", + "AgBAQgoEAABCSgIAAABERhQQAABGSgoGAABIHAIAAABIIgIAAABIKAIAAABILgIAAABIOgIAAABIRAIA", + "AABKUAIAAABMSAIAAABMTgIAAABOBgIAAABQTAIAAAAGGEhMCBAGAg4qAAoMBgIECAAAAAAAAAAAKioq", + "KioqKgICAgYGBAgIBgoKCAwOChAQBhISDAEQKgAEAgQCAgIEBAAAAAAAAAAAKioqKioqKioBAQICAgQE", + "BAYGBggIEAoSEgwUFA4BECoABAIEAgIEBAQAAAAAAAAAACoqKioqKioqAQECAgIEBAQGBgYICBAKEhIM", + "FBQOARI2AAQCBAIEAgQEBAAAAAAAAAAAADY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBAQChISDhQU", + "EAESNgAEAgQCBAIEBAQAAAAAAAAAAAA2NjY2NjY2NjYBAQICAgQEBAYGBggICAoKCgwMEAoSEg4UFBAB", + "ECoABAIEAgQEBAQAAAAAAAAAACoqKioqKioqAQECAgIEBAQGBgYICBAKEhIMFBQOAQ4kAAQCBAQEBAQA", + "AAAAAAAAJCQkJCQkJAEBAgICBAQGBggQCBISChQUDAECAAQAAAACBAwGCAoMEBICBAYICgwO" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index 990732ad85..d8c780180b 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -1827,8 +1827,8 @@ static _serializedATN: [&'static str; 14] = [ "AAAAWFQCAAAAWFoCAAAAWl4CAAAAXFgCAAAAXmAKEAAAYGIKFAAAYg4CAAAAZGYKEAAAZmoKEgAAaGQC", "AAAAamwCAAAAbGgCAAAAbG4CAAAAbnACAAAAcHIKEAAAcnQKFAAAdBICAAAAdngKEAAAeHwKEgAAenYC", "AAAAenwCAAAAfH4CAAAAfoABChAAAIABggEKFAAAggEWAgAAAIQBhgEKFgAAhgGOAQoYAACIAYoBChYA", - "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEGDA4AChgAAAYCBAAAAAAAAAwY", + "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEIDA4AChgAAAYCBAAAAAAAAAwY", "GBgYAgICCAgEBAQGBgYIAgoeAAAEAgAABAAAAAAGGBgYHhoaAgEBBAoKBg4OCBoaAgYIEgAAAgQAAAAA", "AAYSEhIQEAISEgQUFAYICBIAAAIEAAAAAAAGEhISEBACEhIEFBQGCggSAAACBAAAAAAABhISEhAQAhIS", - "BBQUBgwGDAAAAgAAAAAGDAwWFgIYGAQ=" + "BBQUBgwGDAAAAgAAAAAGDAwWFgIYGAQA" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/lr_dfa_tests.rs b/runtime/Rust/tests/lr_dfa_tests.rs new file mode 100644 index 0000000000..280c09d61e --- /dev/null +++ b/runtime/Rust/tests/lr_dfa_tests.rs @@ -0,0 +1,165 @@ +//! Tests for per-precedence static prediction tables (`-Xstatic-dfa` on a +//! left-recursive grammar). +//! +//! The parser in `gen/lrdfaparser.rs` is generated with `-Xstatic-dfa` from +//! `grammars/LrDfa.g4`, a left-recursive expression grammar exercising the +//! shapes that make precedence prediction hard: multiple binary precedence +//! levels, right-associative operators (`^` and the ternary), a prefix +//! operator, a postfix operator, and array indexing (`e '[' e ']'`, whose +//! nested 0-precedence re-entry exercises the precedence-filter suppression +//! path). Every precedence class of the operator-loop decision is +//! statically decidable, so the generated loop runs entirely on +//! `dfa_predict` with a per-precedence table dispatch - the static analogue +//! of the adaptive runtime's per-precedence DFA start states, making the +//! loop behave like a hand-rolled precedence-climbing (Pratt) parser. + +#[rustfmt::skip] +mod gen { + #![allow(non_snake_case)] + #![allow(clippy::all)] + pub mod lrdfalexer; + pub mod lrdfalistener; + pub mod lrdfaparser; +} + +use dbt_antlr4::common_token_stream::CommonTokenStream; +use dbt_antlr4::recognizer::Recognizer; +use dbt_antlr4::token_factory::CommonTokenFactory; +use dbt_antlr4::trees::string_tree; +use dbt_antlr4::{Arena, InputStream}; + +use crate::gen::lrdfalexer::LrDfaLexer; +use crate::gen::lrdfaparser::LrDfaParser; + +fn parse(input: &'static str) -> Result { + Arena::with(|arena| { + let lexer = LrDfaLexer::<_, CommonTokenFactory>::new(arena, InputStream::new(input)); + let tokens = CommonTokenStream::new(lexer); + let mut parser = LrDfaParser::new(arena, tokens); + parser + .s() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + }) +} + +/// Left-associative operators at distinct precedence levels. +#[test] +fn test_precedence_and_left_associativity() { + assert_eq!( + parse("1+2*3").unwrap(), + "(s (e (e 1) + (e (e 2) * (e 3))) )" + ); + assert_eq!( + parse("1*2+3").unwrap(), + "(s (e (e (e 1) * (e 2)) + (e 3)) )" + ); + assert_eq!( + parse("1+2+3").unwrap(), + "(s (e (e (e 1) + (e 2)) + (e 3)) )" + ); + assert_eq!( + parse("1-2-3").unwrap(), + "(s (e (e (e 1) - (e 2)) - (e 3)) )" + ); +} + +/// `^` binds right: `2^3^4` = `2^(3^4)`. +#[test] +fn test_right_associativity() { + assert_eq!( + parse("2^3^4").unwrap(), + "(s (e (e 2) ^ (e (e 3) ^ (e 4))) )" + ); + assert_eq!( + parse("2^3*4").unwrap(), + "(s (e (e (e 2) ^ (e 3)) * (e 4)) )" + ); +} + +/// Prefix minus binds tighter than binary operators but looser than `^`. +#[test] +fn test_prefix_operator() { + assert_eq!(parse("-1+2").unwrap(), "(s (e (e - (e 1)) + (e 2)) )"); + assert_eq!(parse("2^-3").unwrap(), "(s (e (e 2) ^ (e - (e 3))) )"); +} + +/// Postfix factorial binds tightest of the operators. +#[test] +fn test_postfix_operator() { + assert_eq!(parse("1+2!").unwrap(), "(s (e (e 1) + (e (e 2) !)) )"); + assert_eq!(parse("-a!").unwrap(), "(s (e - (e (e a) !)) )"); +} + +/// Array indexing: the nested `e` re-enters the rule with precedence 0 +/// through a call site the precedence filter must not eliminate. +#[test] +fn test_index_suppression_shape() { + assert_eq!(parse("a[1]").unwrap(), "(s (e (e a) [ (e 1) ]) )"); + assert_eq!( + parse("a[1][2]").unwrap(), + "(s (e (e (e a) [ (e 1) ]) [ (e 2) ]) )" + ); + assert_eq!( + parse("a[b?c:d]").unwrap(), + "(s (e (e a) [ (e (e b) ? (e c) : (e d)) ]) )" + ); + assert_eq!( + parse("a[1+2]*3").unwrap(), + "(s (e (e (e a) [ (e (e 1) + (e 2)) ]) * (e 3)) )" + ); +} + +/// The ternary is right-associative and lowest-precedence. +#[test] +fn test_ternary() { + assert_eq!( + parse("a?b:c?d:e").unwrap(), + "(s (e (e a) ? (e b) : (e (e c) ? (e d) : (e e))) )" + ); + assert_eq!( + parse("1+a?b:c+2").unwrap(), + "(s (e (e (e 1) + (e a)) ? (e b) : (e (e c) + (e 2))) )" + ); +} + +/// Everything at once. Prefix minus binds tighter than `^` here because it +/// is a higher alternative in the grammar, so `-2^x` is `(-2)^x`. +#[test] +fn test_mixed() { + assert_eq!( + parse("1*-2^a[3]!+b?c[1]:-d").unwrap(), + "(s (e (e (e (e 1) * (e (e - (e 2)) ^ (e (e (e a) [ (e 3) ]) !))) + (e b)) \ + ? (e (e c) [ (e 1) ]) : (e - (e d))) )" + ); +} + +/// Malformed input is recovered by the default error strategy exactly like +/// under adaptive prediction (verified differentially against an +/// adaptive-prediction build of the same grammar): the dispatch's k=0 exit +/// class and the fallback machinery must not mask genuine syntax errors. +#[test] +fn test_errors_still_reported() { + assert_eq!(parse("1+").unwrap(), "(s (e (e 1) + e) )"); + assert_eq!( + parse("a[").unwrap(), + "(s (e (e a) [ e ) )" + ); + assert_eq!(parse("?a").unwrap(), "(s (e ? a) )"); + assert_eq!(parse("").unwrap(), "(s e )"); + assert_eq!(parse("1]2").unwrap(), "(s (e 1) ] 2)"); +} + +/// The operator loop of the left-recursive rule must be table-driven: no +/// adaptive_predict call sites anywhere in the generated parser. +#[test] +fn test_no_adaptive_predict_in_generated_code() { + let src = include_str!("gen/lrdfaparser.rs"); + assert!( + !src.contains("adaptive_predict"), + "grammars/LrDfa.g4 must generate zero adaptive_predict call sites" + ); + assert!( + src.contains("precedence-dispatched"), + "the operator loop decision must be served by a precedence dispatch" + ); +} diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index 0032923242..63e457dc19 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -417,7 +417,7 @@ public void processNonCombinedGrammar(Grammar g, boolean gencode) { // PRECOMPUTE STATIC SLL PREDICTION TABLES FOR SAFE NON-LL(1) DECISIONS if ( static_dfa && !force_atn && !g.isLexer() && g.atn!=null ) { - g.staticDecisionDFAs = DecisionClassifier.buildTables(g); + DecisionClassifier.buildTables(g); } // GENERATE CODE diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 2740b6d2ec..5885c7d8a3 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -135,6 +135,14 @@ public static class Result { * LLSTAR, or trusted EXACT_AMBIG). */ public StaticDFA dfa; + /** + * For {@link Category#LR_PRECEDENCE} decisions: the per-precedence + * table group, populated only when every precedence class is + * statically decidable (see {@link PrecedenceStaticDFA}). + */ + public PrecedenceStaticDFA precDfa; + /** For LR_PRECEDENCE decisions: report detail (per-class outcomes). */ + public String precNote; public Result(DecisionState decisionState) { this.decisionState = decisionState; @@ -241,6 +249,33 @@ public Result(DecisionState decisionState) { /** Per-attempt memo for {@link #contextDepth} (contexts share structure). */ protected Map depthCache; + // -- precedence-decision construction mode (see classifyPrecedence) -- + + /** + * When true, the start-state closure in progress belongs to a precedence + * loop decision: frame-0 precedence predicates are evaluated + * against {@link #precEvalValue} (mirroring the runtime, which collects + * and evaluates precedence predicates only while computing a precedence + * DFA start state), and precedence-filter suppression marks are placed + * (mirroring {@code outermostPrecedenceReturn} detection in + * ParserATNSimulator#closure_). + */ + protected boolean precStartClosure; + /** Representative precedence of the class under construction. */ + protected int precEvalValue; + /** Rule index of the precedence decision under construction; -1 = none. */ + protected int precRuleIndex = -1; + /** During precedence-mode construction: exact conflicts are not trusted. */ + protected boolean trustExactAmbig = true; + /** + * Lazily built: state number of a rule call's follow state - the state + * grammar-wide FOLLOW links from the callee's stop state point back to - + * mapped to that call's RuleTransition. Used to re-derive, on the + * tool-side ATN, what ATNDeserializer#markPrecedenceDecisions encodes as + * EpsilonTransition#outermostPrecedenceReturn in deserialized ATNs. + */ + protected Map callByFollowState; + public DecisionClassifier(Grammar g) { this.g = g; this.atn = g.atn; @@ -263,8 +298,7 @@ public Result classify(DecisionState s) { return res; } if (isPrecedenceLoopDecision(s)) { - res.category = Category.LR_PRECEDENCE; - return res; + return classifyPrecedence(s); } if (g.decisionLOOK != null && s.decision < g.decisionLOOK.size() && AnalysisPipeline.disjoint(g.decisionLOOK.get(s.decision))) { @@ -301,6 +335,191 @@ protected boolean isPrecedenceLoopDecision(DecisionState s) { && maybeLoopEndState.transition(0).target instanceof RuleStopState; } + // --------------------------------------------------------------------- + // Precedence loop decisions (left-recursive rules) + // --------------------------------------------------------------------- + + /** + * Classify the precedence loop decision of a left-recursive rule and, if + * possible, build its per-precedence static prediction tables. + * + *

The runtime predicts this decision with a precedence DFA: + * a separate lazily-built DFA start state per value of + * {@code parser.getPrecedence()} (see {@code DFA.isPrecedenceDfa} and + * {@code ParserATNSimulator.applyPrecedenceFilter}). The precedence only + * influences prediction through the {@code precpred(_ctx, n)} guards of + * the operator alternatives, all evaluated during start-state + * computation, so precedence values with identical guard outcomes are + * behaviorally indistinguishable: the guard constants {@code n1<... + * + *

Tables are emitted only if every class is statically + * decidable (the runtime dispatch must be total). Exact ambiguities are + * not trusted inside precedence classes: the min-alt substitution + * argument has not been re-established under precedence filtering, so + * such classes conservatively demote the whole decision.

+ */ + protected Result classifyPrecedence(DecisionState s) { + Result res = new Result(s); + res.category = Category.LR_PRECEDENCE; + + // distinct guard constants of this rule's operator alternatives + TreeSet cutSet = new TreeSet(); + for (ATNState st : atn.states) { + if (st == null || st.ruleIndex != s.ruleIndex) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof PrecedencePredicateTransition) { + cutSet.add(((PrecedencePredicateTransition)t).precedence); + } + } + } + if (cutSet.isEmpty()) return res; // not the expected LR shape; stay adaptive + + int[] cutoffs = new int[cutSet.size()]; + int[] reps = new int[cutSet.size()+1]; + int ci = 0; + reps[0] = 0; + for (int cut : cutSet) { + cutoffs[ci] = cut; + reps[ci+1] = cut+1; // first precedence above this cutoff + ci++; + } + + if (callByFollowState == null) { + callByFollowState = new HashMap(); + for (ATNState st : atn.states) { + if (st == null) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + callByFollowState.put(rt.followState.stateNumber, rt); + } + } + } + } + + StaticDFA[] tables = new StaticDFA[reps.length]; + StringBuilder note = new StringBuilder(); + boolean allStatic = true; + int maxK = 0; + int totalStates = 0; + this.precRuleIndex = s.ruleIndex; + this.trustExactAmbig = false; + try { + for (int c = 0; c < reps.length; c++) { + this.precEvalValue = reps[c]; + Result attempt = null; + for (int depthBound : wideningDepths) { + Result a = new Result(s); + a.wideningDepth = depthBound; + if (!buildDFA(s, a, depthBound)) { attempt = a; break; } + attempt = a; // overflow at this bound; try tighter widening + } + res.sawPrecPredicate |= attempt.sawPrecPredicate; + res.usedWidening |= attempt.usedWidening; + if (note.length() > 0) note.append(' '); + note.append("p").append(c == 0 ? "<=" + cutoffs[0] + : c < cutoffs.length ? "=" + (cutoffs[c-1]+1) + ".." + cutoffs[c] + : ">" + cutoffs[cutoffs.length-1]).append(':'); + if (attempt.dfa == null) { + allStatic = false; + note.append(attempt.category); + if (!attempt.contextSensitiveConflicts.isEmpty()) { + note.append("/ctx").append(distinct(attempt.contextSensitiveConflicts)); + } + if (!attempt.approxConflicts.isEmpty()) { + note.append("/approx").append(distinct(attempt.approxConflicts)); + } + if (!attempt.exactAmbigConflicts.isEmpty()) { + note.append("/exact").append(distinct(attempt.exactAmbigConflicts)); + } + if (abortOnUntrustedConflict) break; + } + else { + tables[c] = attempt.dfa; + maxK = Math.max(maxK, attempt.k); + totalStates += attempt.numDfaStates; + note.append(attempt.dfa.cyclic ? "LL(*)" : "k=" + attempt.k); + } + } + } + finally { + this.precRuleIndex = -1; + this.trustExactAmbig = true; + this.precStartClosure = false; + } + + res.precNote = "classes=" + reps.length + " [" + note + "]"; + if (allStatic) { + res.precDfa = new PrecedenceStaticDFA(s.decision, cutoffs, tables); + res.k = maxK; + res.numDfaStates = totalStates; + } + return res; + } + + /** + * Tool-side port of ParserATNSimulator#applyPrecedenceFilter, applied to + * the merged start configuration set of a precedence class before it + * becomes DFA state 0. Pass 1 (evaluating the operator guards on the + * loop-entry alternative) already happened eagerly during closure - see + * the PrecedencePredicateTransition case - so only pass 2 remains: + * eliminate loop-exit configurations shadowed by a loop-entry + * configuration at the same ATN state with an equal context (the + * "let the current invocation take the operator" resolution that makes + * precedence loops unambiguous), keeping configurations whose + * suppression mark identifies them as re-entries through 0-precedence + * call sites (a real outer invocation may legitimately take the + * operator, cf. {@code e '[' e ']'}). + * + *

Because the suppression mark lives above the taint bits in + * {@link ATNConfig#reachesIntoOuterContext} and merging takes the max, + * a merge with a suppressed configuration can swallow taint bits; they + * are conservatively restored from the pre-merge configurations, keyed + * by (state, alt). Suppression marks are cleared from the survivors so + * they cannot perturb DFA state identity downstream.

+ */ + protected Set applyPrecedenceFilter(Set raw) { + // conservative taint restore: OR of pre-merge taints per (state, alt) + Map taintByStateAlt = new HashMap(); + for (ATNConfig c : raw) { + long key = ((long)c.state.stateNumber << 32) | c.alt; + Integer prev = taintByStateAlt.get(key); + int taint = c.reachesIntoOuterContext & (BOUNDARY_TAINT|PRECPRED_TAINT|WIDENED_TAINT); + taintByStateAlt.put(key, prev == null ? taint : (prev|taint)); + } + + Set merged = canonical(raw); + + Map statesFromAlt1 = new HashMap(); + for (ATNConfig c : merged) { + if (c.alt == 1) statesFromAlt1.put(c.state.stateNumber, c.context); + } + + Set result = new LinkedHashSet(); + for (ATNConfig c : merged) { + if (c.alt != 1 && !c.isPrecedenceFilterSuppressed()) { + PredictionContext ctx1 = statesFromAlt1.get(c.state.stateNumber); + if (ctx1 != null && ctx1.equals(c.context)) { + continue; // eliminated: shadowed by the loop-entry alternative + } + } + ATNConfig kept = new ATNConfig(c); + kept.setPrecedenceFilterSuppressed(false); + long key = ((long)c.state.stateNumber << 32) | c.alt; + Integer taint = taintByStateAlt.get(key); + if (taint != null) kept.reachesIntoOuterContext |= taint; + result.add(kept); + } + return result; + } + // --------------------------------------------------------------------- // Static SLL DFA construction // --------------------------------------------------------------------- @@ -318,9 +537,14 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { Set start = new LinkedHashSet(); Set startBusy = new HashSet(); + this.precStartClosure = precRuleIndex >= 0; for (int i = 0; i < s.getNumberOfTransitions(); i++) { closure(new ATNConfig(s.transition(i).target, i+1, EmptyPredictionContext.Instance), - start, startBusy, res); + start, startBusy, res, 0); + } + this.precStartClosure = false; + if (precRuleIndex >= 0) { + start = applyPrecedenceFilter(start); } start = canonical(start); stateIds.put(start, 0); @@ -368,7 +592,11 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { // identically. Mixed usage (dangling-else shape) means // full-context prediction may kill the boundary-only // alternative, so min-alt is not behavior-preserving. - boolean untrusted = hardTainted || (anyBoundary && !allBoundary); + // Inside precedence classes exact conflicts are never + // trusted: the substitution argument has not been + // re-established under precedence filtering. + boolean untrusted = hardTainted || (anyBoundary && !allBoundary) + || !trustExactAmbig; BitSet conflicting = PredictionMode.getAlts(altSubsets); if (untrusted) res.approxConflicts.add(conflicting); else if (exact) res.exactAmbigConflicts.add(conflicting); @@ -583,7 +811,7 @@ else if (t instanceof WildcardTransition) { succ.add(c); } else { - closure(new ATNConfig(c, moveTargets.get(m)), succ, busy, res); + closure(new ATNConfig(c, moveTargets.get(m)), succ, busy, res, 0); } } succ = canonical(succ); @@ -608,8 +836,19 @@ else if (t instanceof WildcardTransition) { * are traversed (and recorded), rule invocations push a singleton context * (widened on recursion), rule stops pop or - with a wildcard context - * chase the grammar-wide FOLLOW links the tool attaches to rule stop states. + * + *

{@code depth} is the runtime's frame-balance counter: +1 per rule + * invocation while non-negative (latched once the closure leaves the + * decision's frame), -1 per return. It exists to identify frame-0 + * precedence predicates ({@code depth == 0}), which the runtime + * evaluates while computing a precedence DFA start state and which are + * evaluated here under the same conditions ({@link #precStartClosure}). + * Boundary FOLLOW chases force the depth negative: under widening a + * return can pop through the boundary from a nominally balanced depth, + * and a predicate reached that way belongs to a phantom frame, never to + * frame 0.

*/ - protected void closure(ATNConfig config, Set configs, Set busy, Result res) { + protected void closure(ATNConfig config, Set configs, Set busy, Result res, int depth) { if (!busy.add(config)) return; ATNState p = config.state; @@ -618,11 +857,11 @@ protected void closure(ATNConfig config, Set configs, Set if (ctx != null && !ctx.isEmpty()) { for (int i = 0; i < ctx.size(); i++) { if (ctx.getReturnState(i) == PredictionContext.EMPTY_RETURN_STATE) { - closure(new ATNConfig(config, p, EmptyPredictionContext.Instance), configs, busy, res); + closure(new ATNConfig(config, p, EmptyPredictionContext.Instance), configs, busy, res, depth); } else { ATNState returnState = atn.states.get(ctx.getReturnState(i)); - closure(new ATNConfig(config, returnState, ctx.getParent(i)), configs, busy, res); + closure(new ATNConfig(config, returnState, ctx.getParent(i)), configs, busy, res, depth-1); } } return; @@ -640,6 +879,10 @@ protected void closure(ATNConfig config, Set configs, Set configs.add(config); } + // p being a rule stop here means the context was empty: the epsilon + // transitions below are the grammar-wide FOLLOW links + boolean boundaryChase = p instanceof RuleStopState; + for (int i = 0; i < p.getNumberOfTransitions(); i++) { Transition t = p.transition(i); if (t instanceof RuleTransition) { @@ -669,21 +912,56 @@ else if (contextDepth(config.context) >= currentDepthBound res.usedWidening = true; callee.reachesIntoOuterContext |= WIDENED_TAINT; } - closure(callee, configs, busy, res); + closure(callee, configs, busy, res, depth >= 0 ? depth+1 : depth); } else if (t instanceof PrecedencePredicateTransition) { - // traversed as epsilon = assumed true: over-approximation - res.sawPrecPredicate = true; - ATNConfig c2 = new ATNConfig(config, t.target); - c2.reachesIntoOuterContext |= PRECPRED_TAINT; - closure(c2, configs, busy, res); + if (precStartClosure && depth == 0) { + // Frame-0 guard of the precedence decision under + // construction: evaluate precpred(n) = n >= p against + // the class representative, exactly like the runtime's + // precedence DFA start-state computation (pass 1 of + // applyPrecedenceFilter). Failing configs are + // eliminated; passing ones continue untainted. + if (((PrecedencePredicateTransition)t).precedence >= precEvalValue) { + closure(new ATNConfig(config, t.target), configs, busy, res, depth); + } + } + else { + // traversed as epsilon = assumed true, matching the + // runtime, which only evaluates precedence predicates + // in frame 0 of a precedence DFA start state + res.sawPrecPredicate = true; + ATNConfig c2 = new ATNConfig(config, t.target); + c2.reachesIntoOuterContext |= PRECPRED_TAINT; + closure(c2, configs, busy, res, depth); + } } else if (t instanceof PredicateTransition) { res.sawPredicate = true; - closure(new ATNConfig(config, t.target), configs, busy, res); + closure(new ATNConfig(config, t.target), configs, busy, res, depth); } else if (t.isEpsilon()) { - closure(new ATNConfig(config, t.target), configs, busy, res); + ATNConfig c2 = new ATNConfig(config, t.target); + int newDepth = depth; + if (boundaryChase) { + // definitively outside frame 0 (see method doc) + newDepth = Math.min(depth-1, -1); + if (precStartClosure && p.ruleIndex == precRuleIndex) { + // Re-derive outermostPrecedenceReturn: this FOLLOW + // link returns from the decision's own rule to a + // call site that invoked it with precedence 0, so a + // real outer invocation may legitimately take an + // operator here - the precedence filter must not + // eliminate this path (ATNDeserializer marks such + // links for ParserATNSimulator#closure_). + RuleTransition call = callByFollowState.get(t.target.stateNumber); + if (call != null && call.precedence == 0 + && call.target.ruleIndex == precRuleIndex) { + c2.setPrecedenceFilterSuppressed(true); + } + } + } + closure(c2, configs, busy, res, newDepth); } } } @@ -788,14 +1066,19 @@ private static int longestPathFrom(int s, List> edges, int[] memo) /** * Build serialized prediction tables for every decision that is * statically decidable with behavior preservation and not already served - * by the LL(1) fast path. Everything else (the "unsafe residue": - * context-sensitive/overflow/predicated/non-greedy/LR-precedence - * decisions) is left to {@code adaptivePredict}. + * by the LL(1) fast path, storing them on the grammar + * ({@link Grammar#staticDecisionDFAs} for plain decisions, + * {@link Grammar#staticPrecedenceDFAs} for the per-precedence table + * groups of left-recursive loop decisions). Everything else (the + * "unsafe residue": context-sensitive/overflow/predicated/non-greedy + * decisions and precedence decisions with any non-static class) is left + * to {@code adaptivePredict}. */ - public static Map buildTables(Grammar g) { + public static void buildTables(Grammar g) { DecisionClassifier classifier = new DecisionClassifier(g); classifier.abortOnUntrustedConflict = true; Map tables = new LinkedHashMap(); + Map precTables = new LinkedHashMap(); for (DecisionState s : g.atn.decisionToState) { // the LL(1) fast path already covers disjoint decisions if (g.decisionLOOK != null && s.decision < g.decisionLOOK.size() @@ -806,8 +1089,12 @@ public static Map buildTables(Grammar g) { if (r.dfa != null) { tables.put(s.decision, r.dfa); } + else if (r.precDfa != null) { + precTables.put(s.decision, r.precDfa); + } } - return tables; + g.staticDecisionDFAs = tables; + g.staticPrecedenceDFAs = precTables; } // --------------------------------------------------------------------- @@ -823,12 +1110,22 @@ public static String report(Grammar g) { for (Category c : Category.values()) counts.put(c, 0); for (Result r : results) counts.put(r.category, counts.get(r.category)+1); + int precStatic = 0; + for (Result r : results) { + if (r.precDfa != null) precStatic++; + } + StringBuilder buf = new StringBuilder(); buf.append("=== decision report: grammar ").append(g.name) .append(" (").append(results.size()).append(" decisions) ===\n"); buf.append("summary:"); for (Map.Entry e : counts.entrySet()) { - if (e.getValue() > 0) buf.append(' ').append(e.getKey()).append('=').append(e.getValue()); + if (e.getValue() > 0) { + buf.append(' ').append(e.getKey()).append('=').append(e.getValue()); + if (e.getKey() == Category.LR_PRECEDENCE && precStatic > 0) { + buf.append('(').append(precStatic).append(" static)"); + } + } } buf.append('\n'); @@ -836,7 +1133,17 @@ public static String report(Grammar g) { int maxKLLK = 0; Map llkHistogram = new java.util.TreeMap(); for (Result r : results) { - if (r.category == Category.LL1 || r.category == Category.LR_PRECEDENCE) continue; + if (r.category == Category.LL1) continue; + if (r.category == Category.LR_PRECEDENCE) { + if (r.precNote != null) { + Rule lrRule = g.getRule(r.decisionState.ruleIndex); + buf.append(String.format("%-22s d=%-4d %-17s", lrRule.name, + r.decisionState.decision, r.category)); + buf.append(' ').append(r.precNote) + .append(r.precDfa != null ? " [static]" : " [adaptive]").append('\n'); + } + continue; + } if (r.k > maxKAnyAcyclic) maxKAnyAcyclic = r.k; if (r.category == Category.LLK) { maxKLLK = Math.max(maxKLLK, r.k); diff --git a/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java b/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java new file mode 100644 index 0000000000..61df1d5fb5 --- /dev/null +++ b/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.analysis; + +/** + * The statically-precomputed prediction tables of one left-recursive + * precedence loop decision (the {@code StarLoopEntryState} the left-recursion + * transformer generates), produced by {@link DecisionClassifier}. + * + *

Such a decision cannot be served by a single static DFA because its + * behavior depends on the current precedence (the {@code _p} argument of the + * rewritten rule): each operator alternative is guarded by + * {@code precpred(_ctx, n)}, which holds iff {@code n >= _p}. The runtime's + * adaptive engine handles this by maintaining a separate DFA start state per + * precedence value ({@code DFA.isPrecedenceDfa()}). Statically, the guard + * constants {@code n1 < ... < nk} appearing in the rule partition all + * precedence values into at most {@code k+1} equivalence classes with + * identical guard outcomes, so the complete behavior is captured by one + * {@link StaticDFA} per class.

+ * + *

Dispatch: the class of precedence {@code p} is the number of cutoffs + * strictly less than {@code p}; the walker computes it from + * {@code parser.getPrecedence()} (the top of the precedence stack, exactly + * the value the adaptive runtime keys its per-precedence start states on). + * Class 0 (p at most n1) has every operator viable; the last class + * (p greater than nk) has none, so its table accepts the loop-exit + * alternative with zero lookahead - together these make the generated loop + * behave like a hand-rolled precedence-climbing (Pratt) parser.

+ */ +public class PrecedenceStaticDFA { + public final int decision; + /** Sorted distinct precedence-guard constants; class(p) = |{c : c < p}|. */ + public final int[] cutoffs; + /** One table per precedence class; length {@code cutoffs.length + 1}. */ + public final StaticDFA[] tables; + + public PrecedenceStaticDFA(int decision, int[] cutoffs, StaticDFA[] tables) { + this.decision = decision; + this.cutoffs = cutoffs; + this.tables = tables; + } +} diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index e6bc427730..c92962c4ad 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -256,9 +256,9 @@ else if ( ebnfRoot.getType()==ANTLRParser.CLOSURE ) { * this target) for the given decision? See -Xstatic-dfa. */ protected boolean hasStaticDFA(int decision) { - return g.staticDecisionDFAs!=null - && g.staticDecisionDFAs.containsKey(decision) - && gen.getTarget().supportsStaticDFA(); + if ( !gen.getTarget().supportsStaticDFA() ) return false; + return (g.staticDecisionDFAs!=null && g.staticDecisionDFAs.containsKey(decision)) + || (g.staticPrecedenceDFAs!=null && g.staticPrecedenceDFAs.containsKey(decision)); } /** Like getComplexEBNFBlock but driving the decision from a static DFA table. */ diff --git a/tool/src/org/antlr/v4/codegen/model/Parser.java b/tool/src/org/antlr/v4/codegen/model/Parser.java index de556a814e..e885ee128a 100644 --- a/tool/src/org/antlr/v4/codegen/model/Parser.java +++ b/tool/src/org/antlr/v4/codegen/model/Parser.java @@ -33,10 +33,13 @@ public Parser(OutputModelFactory factory, ParserFile file) { super(factory); this.file = file; // who contains us? Grammar g = factory.getGrammar(); - if ( g.staticDecisionDFAs!=null && !g.staticDecisionDFAs.isEmpty() + boolean haveTables = + (g.staticDecisionDFAs!=null && !g.staticDecisionDFAs.isEmpty()) + || (g.staticPrecedenceDFAs!=null && !g.staticPrecedenceDFAs.isEmpty()); + if ( haveTables && factory.getGenerator().getTarget().supportsStaticDFA() && !factory.getGenerator().getTarget().isATNSerializedAsBase64VarInts() ) { - staticDFAs = new SerializedStaticDFAs(factory, g.staticDecisionDFAs); + staticDFAs = new SerializedStaticDFAs(factory, g.staticDecisionDFAs, g.staticPrecedenceDFAs); } } } diff --git a/tool/src/org/antlr/v4/codegen/model/SerializedBase64ATN.java b/tool/src/org/antlr/v4/codegen/model/SerializedBase64ATN.java index 69b73709d1..f25f04f914 100644 --- a/tool/src/org/antlr/v4/codegen/model/SerializedBase64ATN.java +++ b/tool/src/org/antlr/v4/codegen/model/SerializedBase64ATN.java @@ -41,12 +41,16 @@ public SerializedBase64ATN(OutputModelFactory factory, ATN atn) { for (int v : serialized) data.add(v); Grammar g = factory.getGrammar(); - if ( g.staticDecisionDFAs!=null && !g.staticDecisionDFAs.isEmpty() - && g.atn==atn + boolean haveTables = + (g.staticDecisionDFAs!=null && !g.staticDecisionDFAs.isEmpty()) + || (g.staticPrecedenceDFAs!=null && !g.staticPrecedenceDFAs.isEmpty()); + int n = 0; + if ( haveTables && g.atn==atn && factory.getGenerator().getTarget().supportsStaticDFA() ) { - SerializedStaticDFAs.appendIntStream(g.staticDecisionDFAs, data, tableComments); + n = SerializedStaticDFAs.appendIntStream( + g.staticDecisionDFAs, g.staticPrecedenceDFAs, data, tableComments); } - numTables = tableComments.size(); + numTables = n; segments = CompactSerializer.encode(data.toArray()); } diff --git a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java index a77639b3b8..725dc50cce 100644 --- a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java +++ b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java @@ -6,20 +6,23 @@ package org.antlr.v4.codegen.model; +import org.antlr.v4.analysis.PrecedenceStaticDFA; import org.antlr.v4.analysis.StaticDFA; import org.antlr.v4.codegen.CompactSerializer; import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.runtime.misc.IntegerList; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; /** * All statically-precomputed SLL prediction tables of a parser - * (see {@link StaticDFA}), packed into one compact serialized blob - - * in the same vein as {@code _serializedATN} - and lazily deserialized by - * the target runtime's {@code StaticDFATables} at first use. + * (see {@link StaticDFA} and {@link PrecedenceStaticDFA}), packed into one + * compact serialized blob - in the same vein as {@code _serializedATN} - and + * lazily deserialized by the target runtime's {@code StaticDFATables} at + * first use. * *

The logical int stream below is encoded with * {@link CompactSerializer} (zigzag LEB128 varints, base64, 80-column line @@ -30,17 +33,26 @@ * numTables * numDecisionSlots (max decision number + 1) * for each table: - * decision + * decision (-1: referenced only via a dispatch below) * numStates * numEdgeInts * accepts[numStates] (predicted alt per state; 0 = non-accept) * fallbacks[numStates] (error-avoidance alt per state; 0 = none) * edgeOffsets[numStates+1] (index of each state's first edge int) * edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) + * numPrecedenceDispatches + * for each dispatch: (a left-recursive precedence loop decision) + * decision + * numCutoffs + * cutoffs[numCutoffs] (sorted; class(p) = #cutoffs < p) + * tableIndex[numCutoffs+1] (table of each precedence class) * + * + *

Identical class tables are deduplicated by content and shared through + * their table index.

*/ public class SerializedStaticDFAs extends OutputModelObject { - public static final int FORMAT_VERSION = 3; + public static final int FORMAT_VERSION = 4; public final int numTables; /** Base64 text segments of the serialized blob, one rendered per line. */ @@ -48,42 +60,102 @@ public class SerializedStaticDFAs extends OutputModelObject { /** One human-readable provenance line per table, for a generated comment. */ public final List tableComments = new ArrayList(); - public SerializedStaticDFAs(OutputModelFactory factory, Map dfas) { + public SerializedStaticDFAs(OutputModelFactory factory, + Map dfas, + Map precDfas) { super(factory); - this.numTables = dfas.size(); IntegerList data = new IntegerList(); - appendIntStream(dfas, data, tableComments); + this.numTables = appendIntStream(dfas, precDfas, data, tableComments); segments = CompactSerializer.encode(data.toArray()); } /** * Append the logical int stream for the tables to {@code data} and one - * provenance line per table to {@code comments}. Shared with - * {@link SerializedBase64ATN}, which appends the stream after the ATN - * ints so both are decoded from a single blob. + * provenance line per table/dispatch to {@code comments}; returns the + * number of tables written. Shared with {@link SerializedBase64ATN}, + * which appends the stream after the ATN ints so both are decoded from + * a single blob. */ - public static void appendIntStream(Map dfas, - IntegerList data, - List comments) { + public static int appendIntStream(Map dfas, + Map precDfas, + IntegerList data, + List comments) { + List tables = new ArrayList(); + List tableDecisions = new ArrayList(); int numDecisionSlots = 0; - for (StaticDFA dfa : dfas.values()) { - numDecisionSlots = Math.max(numDecisionSlots, dfa.decision+1); + + if (dfas != null) { + for (StaticDFA dfa : dfas.values()) { + tables.add(dfa); + tableDecisions.add(dfa.decision); + numDecisionSlots = Math.max(numDecisionSlots, dfa.decision+1); + } + } + + // dispatches reference class tables by index, deduplicated by content + List dispatches = new ArrayList(); + if (precDfas != null) { + for (PrecedenceStaticDFA group : precDfas.values()) { + numDecisionSlots = Math.max(numDecisionSlots, group.decision+1); + int[] entry = new int[2 + group.cutoffs.length + group.tables.length]; + entry[0] = group.decision; + entry[1] = group.cutoffs.length; + System.arraycopy(group.cutoffs, 0, entry, 2, group.cutoffs.length); + StringBuilder comment = new StringBuilder("decision "+group.decision + +": precedence-dispatched over cutoffs "+Arrays.toString(group.cutoffs) + +", tables"); + for (int c = 0; c < group.tables.length; c++) { + StaticDFA t = group.tables[c]; + int idx = indexOf(tables, t); + if (idx < 0) { + idx = tables.size(); + tables.add(t); + tableDecisions.add(-1); + } + entry[2 + group.cutoffs.length + c] = idx; + comment.append(c == 0 ? " [" : " ").append(idx); + } + comment.append(']'); + dispatches.add(entry); + comments.add(comment.toString()); + } } data.add(FORMAT_VERSION); - data.add(dfas.size()); + data.add(tables.size()); data.add(numDecisionSlots); - for (StaticDFA dfa : dfas.values()) { - data.add(dfa.decision); + for (int i = 0; i < tables.size(); i++) { + StaticDFA dfa = tables.get(i); + data.add(tableDecisions.get(i)); data.add(dfa.numStates); data.add(dfa.edges.length); for (int v : dfa.accepts) data.add(v); for (int v : dfa.fallbacks) data.add(v); for (int v : dfa.edgeOffsets) data.add(v); for (int v : dfa.edges) data.add(v); - comments.add("decision "+dfa.decision+": " - +(dfa.cyclic ? "LL(*) cyclic" : "LL(k), k="+dfa.maxK) + comments.add((tableDecisions.get(i) >= 0 + ? "decision "+dfa.decision : "table "+i+" (decision "+dfa.decision+")") + +": "+(dfa.cyclic ? "LL(*) cyclic" : "LL(k), k="+dfa.maxK) +", "+dfa.numStates+" states"); } + data.add(dispatches.size()); + for (int[] entry : dispatches) { + for (int v : entry) data.add(v); + } + return tables.size(); + } + + /** Index of a table with identical content, or -1. */ + private static int indexOf(List tables, StaticDFA t) { + for (int i = 0; i < tables.size(); i++) { + StaticDFA o = tables.get(i); + if (o == t || (Arrays.equals(o.accepts, t.accepts) + && Arrays.equals(o.fallbacks, t.fallbacks) + && Arrays.equals(o.edgeOffsets, t.edgeOffsets) + && Arrays.equals(o.edges, t.edges))) { + return i; + } + } + return -1; } } diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index bfb4a5722c..773713905f 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -196,6 +196,14 @@ public class Grammar implements AttributeResolver { */ public Map staticDecisionDFAs; + /** + * Per-precedence static prediction table groups of left-recursive + * precedence loop decisions (see + * {@link org.antlr.v4.analysis.PrecedenceStaticDFA}), keyed by decision + * number; populated only with -Xstatic-dfa. + */ + public Map staticPrecedenceDFAs; + public final Tool tool; /** Token names and literal tokens like "void" are uniquely indexed. From 353ced224782b5af28955609275cd278263c8565 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sun, 12 Jul 2026 17:07:10 -0400 Subject: [PATCH 06/48] Hybrid static tables with adaptive escape (wire v5) The 17 OVERFLOW decisions per SQL grammar were not wrong analyses but impractically large ones: decisions like 'expression (AS? alias)?' or 'identifier (DOT pathComponent)* ' have tiny alternatives that pop through the decision boundary immediately, so all their lookahead beyond a couple of tokens lives in the grammar-wide phantom FOLLOW space (instrumentation showed >99% boundary-tainted configurations concentrated in unrelated rules). The complete SLL DFA over that space is effectively unbounded - the adaptive runtime only wins by building it lazily per input. No pruning fixes an enumeration problem, so stop enumerating: cap the table and keep the reference engine for the rest. A hybrid table is the BFS prefix of the exact-context SLL DFA (depth <= 4, <= 64 states by default) whose remaining states are escapes: untrusted conflicts and the beyond-budget frontier get accepts[s] = -1, where the walker abandons the table and the call site reruns the prediction through adaptivePredict. dfa_predict never consumes input, so the rescan is trivially sound: the table only short-circuits lookahead prefixes it fully proved, the adaptive engine handles everything else. BFS order means the emitted prefix is exactly the shallow states where dynamic predictions concentrate; a reachability-based coverage metric (share of start-state token space that can complete some prediction in-table) gates emission so tables that could never resolve anything are not generated at all. This also generalizes the per-precedence dispatch: classes are no longer all-or-nothing. A precedence class may be fully static, hybrid, or table-less (dispatch entry -1 = straight to adaptivePredict), so the operator loops of booleanExpression/valueExpression go static at 98-100% coverage with only the genuinely context-sensitive corners escaping (the BETWEEN...AND collision - verified differentially on a minimal repro grammar, 12/12 including nested BETWEENs). Also included: precedence guards in lookahead are now evaluated against the constant call-site precedence recovered from the configuration's context top (callByFollowState), instead of assumed-true, whenever the entry precedence is statically known - pruning the redundant derivations that inflate precedence-ladder closures. Unknown or ambiguous entry precedence falls back to assumed-true + taint as before. A -Dantlr.dfa.debug dump of overflow config populations is kept for future tuning. Wire format v5: accepts may be -1 (escape), dispatch table indices may be -1 (adaptive class). Rust walker returns INVALID_ALT to defer; the staticDFAPredict template inlines the fallback at each call site. Java defers inside Parser.dfaPredict via getInterpreter().adaptivePredict. New permanent differential fuzz harness: grammars/FuzzExpr.g4 (precedence ladder + scan-past-expression hybrid decision + a soft keyword making 'as' a valid identifier, so escapes are exercised dynamically) is generated twice - with -Xstatic-dfa into tests/gen and adaptive into tests/gen/adaptive - and tests/fuzz_differential_tests.rs drives 800 fixed-seed random inputs (grammar-directed and token soup) plus pinned soft-keyword corners through both parsers, asserting identical trees. Results across the six SQL grammars: OVERFLOW and CONTEXT_SENSITIVE residue eliminated entirely; every LR precedence loop static; zero bare adaptive_predict call sites remain (every prediction is table-first); generated parser size +3.7% to +7.3%. Verified: full cargo test incl. fuzz, RustStaticDFARuntimeTests + RustRuntimeTests 707/707, tool-testsuite 694, Java probes 24/24 + 8/8 + 12/12 escape corners. Signed-off-by: Bo Lin --- .../Java/src/org/antlr/v4/runtime/Parser.java | 10 + .../antlr/v4/runtime/atn/StaticDFATables.java | 19 +- runtime/Rust/gen_test_grammars.sh | 9 + runtime/Rust/grammars/FuzzExpr.g4 | 41 + runtime/Rust/src/parser.rs | 25 +- runtime/Rust/src/static_dfa.rs | 36 +- runtime/Rust/tests/fuzz_differential_tests.rs | 217 +++ .../gen/adaptive/fuzzexprbaselistener.rs | 83 ++ .../Rust/tests/gen/adaptive/fuzzexprlexer.rs | 145 ++ .../tests/gen/adaptive/fuzzexprlistener.rs | 60 + .../Rust/tests/gen/adaptive/fuzzexprparser.rs | 1208 ++++++++++++++++ .../Rust/tests/gen/fuzzexprbaselistener.rs | 83 ++ runtime/Rust/tests/gen/fuzzexprlexer.rs | 145 ++ runtime/Rust/tests/gen/fuzzexprlistener.rs | 60 + runtime/Rust/tests/gen/fuzzexprparser.rs | 1233 +++++++++++++++++ runtime/Rust/tests/gen/lrdfaparser.rs | 8 +- runtime/Rust/tests/gen/staticdfaparser.rs | 16 +- runtime/Rust/tests/lr_dfa_tests.rs | 11 +- runtime/Rust/tests/static_dfa_tests.rs | 11 +- .../v4/tool/templates/codegen/Rust/Rust.stg | 6 +- .../antlr/v4/analysis/DecisionClassifier.java | 372 ++++- .../v4/analysis/PrecedenceStaticDFA.java | 6 +- tool/src/org/antlr/v4/analysis/StaticDFA.java | 10 +- .../codegen/model/SerializedStaticDFAs.java | 31 +- 24 files changed, 3763 insertions(+), 82 deletions(-) create mode 100644 runtime/Rust/grammars/FuzzExpr.g4 create mode 100644 runtime/Rust/tests/fuzz_differential_tests.rs create mode 100644 runtime/Rust/tests/gen/adaptive/fuzzexprbaselistener.rs create mode 100644 runtime/Rust/tests/gen/adaptive/fuzzexprlexer.rs create mode 100644 runtime/Rust/tests/gen/adaptive/fuzzexprlistener.rs create mode 100644 runtime/Rust/tests/gen/adaptive/fuzzexprparser.rs create mode 100644 runtime/Rust/tests/gen/fuzzexprbaselistener.rs create mode 100644 runtime/Rust/tests/gen/fuzzexprlexer.rs create mode 100644 runtime/Rust/tests/gen/fuzzexprlistener.rs create mode 100644 runtime/Rust/tests/gen/fuzzexprparser.rs diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java index d484d4c384..d521d8d8e4 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java @@ -549,11 +549,21 @@ public int dfaPredict(StaticDFATables tables, int decision) // the precedence selects the table of dispatched decisions (the // operator loops of left-recursive rules); plain decisions ignore it int table = tables.tableFor(decision, getPrecedence()); + if ( table<0 ) { + // this precedence class has no static table + return getInterpreter().adaptivePredict(_input, decision, _ctx); + } int s = 0; int i = 1; while (true) { int alt = tables.accept(table, s); if ( alt>0 ) return alt; + if ( alt==StaticDFATables.ESCAPE ) { + // hybrid-table escape: rerun the prediction through the + // adaptive engine (no input was consumed, so the rescan + // starts clean) + return getInterpreter().adaptivePredict(_input, decision, _ctx); + } int next = tables.edge(table, s, _input.LA(i)); if ( next<0 ) { // No viable transition. If some alternative already finished diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java index e107ce918e..297d46c68a 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java @@ -30,7 +30,8 @@ * decision (-1: referenced only via a dispatch below) * numStates * numEdgeInts - * accepts[numStates] (predicted alt per state; 0 = non-accept) + * accepts[numStates] (predicted alt per state; 0 = non-accept; + * -1 = escape: defer to adaptivePredict) * fallbacks[numStates] (error-avoidance alt per state; 0 = none) * edgeOffsets[numStates+1] (index of each state's first edge int) * edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) @@ -39,7 +40,8 @@ * decision * numCutoffs * cutoffs[numCutoffs] (sorted; class(p) = #cutoffs < p) - * tableIndex[numCutoffs+1] (table of each precedence class) + * tableIndex[numCutoffs+1] (table of each precedence class; + * -1 = class dispatches to adaptivePredict) * * *

State 0 of each table is its start state; {@code accepts[s] > 0} marks @@ -58,7 +60,7 @@ */ public class StaticDFATables { /** Must match the tool's SerializedStaticDFAs.FORMAT_VERSION. */ - public static final int FORMAT_VERSION = 4; + public static final int FORMAT_VERSION = 5; /** Concatenated per-table data: accepts, fallbacks, edgeOffsets, edges. */ protected final int[] data; @@ -139,11 +141,17 @@ public static StaticDFATables deserialize(String[] segments) { return new StaticDFATables(data.toArray(), metas, decisionToTable, dispatchData.toArray()); } + /** {@code accepts} sentinel: a hybrid table's escape state - the walker + * defers the whole prediction to {@code adaptivePredict}. */ + public static final int ESCAPE = -1; + /** * The table serving {@code decision}: {@code precedence} (the parser's * current precedence, i.e. the top of its precedence stack) selects the * precedence class of dispatched decisions - the operator loops of - * left-recursive rules - and is ignored for plain ones. + * left-recursive rules - and is ignored for plain ones. Returns -1 when + * the selected precedence class has no static table and the prediction + * must run through {@code adaptivePredict}. */ public int tableFor(int decision, int precedence) { int table = decisionToTable[decision]; @@ -158,7 +166,8 @@ public int tableFor(int decision, int precedence) { return table; } - /** Predicted alternative if {@code state} of {@code table} accepts; else 0. */ + /** Predicted alternative if {@code state} of {@code table} accepts; + * 0 = not an accept state; {@link #ESCAPE} = escape state. */ public int accept(int table, int state) { int acceptsAt = metas[table*5]; return data[acceptsAt+state]; diff --git a/runtime/Rust/gen_test_grammars.sh b/runtime/Rust/gen_test_grammars.sh index 4e4494ef37..2e5a63eaf7 100755 --- a/runtime/Rust/gen_test_grammars.sh +++ b/runtime/Rust/gen_test_grammars.sh @@ -15,6 +15,7 @@ declare -a GRAMMARS=( "Labels" "StaticDFA" "LrDfa" + "FuzzExpr" # "FHIRPath" ) @@ -28,6 +29,7 @@ declare -a ADDITIONAL_ARGS=( "" "-Xstatic-dfa" "-Xstatic-dfa" + "-Xstatic-dfa" ) for i in "${!GRAMMARS[@]}"; do @@ -43,3 +45,10 @@ for i in "${!GRAMMARS[@]}"; do echo "Generating: $grammar" (cd "$SCRIPT_DIR/grammars" && "${cmd[@]}") done + +# The differential-fuzz twin: FuzzExpr generated WITHOUT -Xstatic-dfa into a +# sibling module, so tests can compare table-driven and adaptive prediction +# on the same grammar (tests/fuzz_differential_tests.rs). +echo "Generating: FuzzExpr (adaptive twin)" +(cd "$SCRIPT_DIR/grammars" && java -cp "$ANTLR_PATH" org.antlr.v4.Tool -Dlanguage=Rust \ + -o ../tests/gen/adaptive FuzzExpr.g4) diff --git a/runtime/Rust/grammars/FuzzExpr.g4 b/runtime/Rust/grammars/FuzzExpr.g4 new file mode 100644 index 0000000000..0fb73e416b --- /dev/null +++ b/runtime/Rust/grammars/FuzzExpr.g4 @@ -0,0 +1,41 @@ +// Differential-fuzz grammar for -Xstatic-dfa (see tests/fuzz_differential_tests.rs). +// Concentrates the decision shapes that exercise hybrid tables and +// per-precedence dispatch: +// - a full precedence ladder (left/right-associative binary operators, +// prefix, postfix, indexing, calls, parens); +// - selectItem-shaped decisions ('e AS ID | e') that must scan past an +// unbounded expression - the classic hybrid-table candidate; +// - a soft keyword ('as' is also a valid identifier via `name`), so the +// alias decision has genuinely context-sensitive corners that resolve +// through the escape path at runtime. +grammar FuzzExpr; + +s : item (',' item)* ';'? EOF ; + +item + : e 'as' name + | e + ; + +name : ID | 'as' ; + +q : name ('.' name)* ; + +e : e '[' e ']' + | '-' e + | e '^' e + | e ('*'|'/') e + | e ('+'|'-') e + | atom + ; + +atom + : q + | INT + | '(' e ')' + | ID '(' (e (',' e)*)? ')' + ; + +ID : [a-z]+ ; +INT : [0-9]+ ; +WS : [ \t\r\n]+ -> skip ; diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 764a549672..adffbcfda8 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -476,21 +476,36 @@ where /// per-prediction allocation. /// /// Returns the predicted alternative (1-based, decision-transition - /// numbering identical to `adaptive_predict`). A lookahead token - /// matching no table edge produces a `NoViableAlt` error anchored at the - /// decision start token, matching `adaptive_predict`'s convention. + /// numbering identical to `adaptive_predict`), or + /// [`crate::atn::INVALID_ALT`] (0) when the table defers the prediction + /// to the adaptive engine - a hybrid table's escape state, or a + /// precedence class without a table. Generated call sites rerun such + /// predictions through `adaptive_predict` (sound: the walker never + /// consumes input). A lookahead token matching no table edge produces a + /// `NoViableAlt` error anchored at the decision start token, matching + /// `adaptive_predict`'s convention. pub fn dfa_predict(&mut self, decision: i32) -> Result { // the precedence selects the table of dispatched decisions (the // operator loops of left-recursive rules); plain decisions ignore it let precedence = self.get_precedence(); - let dfa = self + let Some(dfa) = self .atn_manager .atn() .static_dfas - .table(decision, precedence); + .table(decision, precedence) + else { + // this precedence class has no static table + return Ok(crate::atn::INVALID_ALT); + }; let mut s = 0usize; let mut i = 1isize; loop { + if dfa.is_escape(s) { + // hybrid-table escape: the caller reruns the prediction + // through the adaptive engine (no input was consumed, so + // the rescan starts clean) + return Ok(crate::atn::INVALID_ALT); + } if let Some(alt) = dfa.accept(s) { return Ok(alt); } diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs index ec3d740ff8..0f9896527b 100644 --- a/runtime/Rust/src/static_dfa.rs +++ b/runtime/Rust/src/static_dfa.rs @@ -24,7 +24,8 @@ //! decision (-1: referenced only via a dispatch below) //! numStates //! numEdgeInts -//! accepts[numStates] (predicted alt per state; 0 = non-accept) +//! accepts[numStates] (predicted alt per state; 0 = non-accept; +//! -1 = escape: defer to adaptive prediction) //! fallbacks[numStates] (error-avoidance alt per state; 0 = none) //! edgeOffsets[numStates+1] (index of each state's first edge i32) //! edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) @@ -33,7 +34,8 @@ //! decision //! numCutoffs //! cutoffs[numCutoffs] (sorted; class(p) = #cutoffs < p) -//! tableIndex[numCutoffs+1] (table of each precedence class) +//! tableIndex[numCutoffs+1] (table of each precedence class; +//! -1 = class dispatches to adaptive prediction) //! ``` //! //! Precedence dispatches serve the operator loops of left-recursive rules: @@ -46,7 +48,7 @@ /// Format version understood by this runtime; must match the tool's /// `SerializedStaticDFAs.FORMAT_VERSION`. -pub const FORMAT_VERSION: i32 = 4; +pub const FORMAT_VERSION: i32 = 5; /// The deserialized static prediction tables of one generated parser. /// @@ -184,10 +186,12 @@ impl StaticDFATables { /// The table for a decision; `precedence` (the parser's current /// precedence, i.e. the top of its precedence stack) selects the /// precedence class of dispatched decisions and is ignored for plain - /// ones. Panics if the decision has no static table (generated code - /// only references decisions it has tables for). + /// ones. `None` means the selected precedence class has no static + /// table and the prediction must run through the adaptive engine. + /// Panics if the decision itself has no table entry at all (generated + /// code only references decisions it has tables for). #[inline] - pub fn table(&self, decision: i32, precedence: i32) -> StaticDFATable<'_> { + pub fn table(&self, decision: i32, precedence: i32) -> Option> { let mut t = self.decision_to_table[decision as usize]; if t <= -2 { // precedence dispatch: class(p) = #cutoffs < p @@ -196,6 +200,10 @@ impl StaticDFATables { let cutoffs = &self.dispatch_data[at + 1..at + 1 + num_cutoffs]; let class = cutoffs.iter().take_while(|&&c| c < precedence).count(); t = self.dispatch_data[at + 1 + num_cutoffs + class]; + if t < 0 { + // this precedence class dispatches to adaptive prediction + return None; + } } assert!(t >= 0, "no static DFA table for decision {}", decision); let (accepts_at, fallbacks_at, edge_offsets_at, edges_at) = self.metas[t as usize]; @@ -204,15 +212,20 @@ impl StaticDFATables { .get(t as usize + 1) .map(|m| m.0) .unwrap_or(self.data.len()); - StaticDFATable { + Some(StaticDFATable { accepts: &self.data[accepts_at..fallbacks_at], fallbacks: &self.data[fallbacks_at..edge_offsets_at], edge_offsets: &self.data[edge_offsets_at..edges_at], edges: &self.data[edges_at..end], - } + }) } } +/// `accepts` sentinel: an escape state of a hybrid table - the walker +/// defers the whole prediction to the adaptive engine (the table never +/// consumes input, so the rescan is trivially sound). +pub const ESCAPE: i32 = -1; + impl<'a> StaticDFATable<'a> { /// Predicted alternative if `state` is an accept state. #[inline] @@ -225,6 +238,13 @@ impl<'a> StaticDFATable<'a> { } } + /// True if `state` is an escape state: prediction must be handed to + /// the adaptive engine. + #[inline] + pub fn is_escape(&self, state: usize) -> bool { + self.accepts[state] == ESCAPE + } + /// Error-avoidance fallback alternative of `state`, if any. #[inline] pub fn fallback(&self, state: usize) -> Option { diff --git a/runtime/Rust/tests/fuzz_differential_tests.rs b/runtime/Rust/tests/fuzz_differential_tests.rs new file mode 100644 index 0000000000..88eb868866 --- /dev/null +++ b/runtime/Rust/tests/fuzz_differential_tests.rs @@ -0,0 +1,217 @@ +//! Differential fuzz of table-driven vs adaptive prediction. +//! +//! `gen/fuzzexprparser.rs` is generated from `grammars/FuzzExpr.g4` with +//! `-Xstatic-dfa`; `gen/adaptive/fuzzexprparser.rs` is the same grammar +//! without it. The grammar concentrates everything the static tables must +//! get right: a precedence ladder driven by per-precedence dispatch, a +//! scan-past-expression decision served by a hybrid table with adaptive +//! escapes, and a soft keyword (`as` doubles as an identifier) whose +//! genuinely context-sensitive corners exercise the escape path at +//! runtime. +//! +//! Every input - grammar-directed random expressions and unconstrained +//! token soup, from a fixed-seed generator so failures reproduce - must +//! produce an identical parse tree (or identically fail) under both +//! parsers. `dfa_predict` never consumes input before escaping, so any +//! divergence is a real prediction bug, not a harness artifact. + +#[rustfmt::skip] +mod gen { + #![allow(non_snake_case)] + #![allow(clippy::all)] + pub mod fuzzexprlexer; + pub mod fuzzexprlistener; + pub mod fuzzexprparser; + pub mod adaptive { + pub mod fuzzexprlexer; + pub mod fuzzexprlistener; + pub mod fuzzexprparser; + } +} + +use dbt_antlr4::common_token_stream::CommonTokenStream; +use dbt_antlr4::recognizer::Recognizer; +use dbt_antlr4::token_factory::CommonTokenFactory; +use dbt_antlr4::trees::string_tree; +use dbt_antlr4::{Arena, InputStream}; + +fn parse_static(input: &str) -> Result { + Arena::with(|arena| { + let lexer = gen::fuzzexprlexer::FuzzExprLexer::<_, CommonTokenFactory>::new( + arena, + InputStream::new(input), + ); + let tokens = CommonTokenStream::new(lexer); + let mut parser = gen::fuzzexprparser::FuzzExprParser::new(arena, tokens); + parser + .s() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + .map_err(|e| format!("{e:?}")) + }) +} + +fn parse_adaptive(input: &str) -> Result { + Arena::with(|arena| { + let lexer = gen::adaptive::fuzzexprlexer::FuzzExprLexer::<_, CommonTokenFactory>::new( + arena, + InputStream::new(input), + ); + let tokens = CommonTokenStream::new(lexer); + let mut parser = gen::adaptive::fuzzexprparser::FuzzExprParser::new(arena, tokens); + parser + .s() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + .map_err(|e| format!("{e:?}")) + }) +} + +fn assert_equivalent(input: &str) { + let s = parse_static(input); + let a = parse_adaptive(input); + match (&s, &a) { + (Ok(st), Ok(at)) => assert_eq!(st, at, "tree divergence on input: {input:?}"), + (Err(_), Err(_)) => {} // both unrecoverable; exact error compared in Java probes + _ => panic!("outcome divergence on input {input:?}:\n static: {s:?}\n adaptive: {a:?}"), + } +} + +/// Deterministic xorshift64* PRNG: fixed seeds, reproducible failures. +struct Rng(u64); + +impl Rng { + fn next(&mut self) -> u64 { + self.0 ^= self.0 >> 12; + self.0 ^= self.0 << 25; + self.0 ^= self.0 >> 27; + self.0.wrapping_mul(0x2545F4914F6CDD1D) + } + + fn below(&mut self, n: usize) -> usize { + (self.next() % n as u64) as usize + } +} + +/// Grammar-directed random expression, depth-bounded. +fn gen_expr(rng: &mut Rng, depth: usize, out: &mut String) { + if depth == 0 || rng.below(4) == 0 { + // atom + match rng.below(6) { + 0 => out.push_str("x"), + 1 => out.push_str("1"), + 2 => out.push_str("as"), // soft keyword as identifier + 3 => out.push_str("a.b"), + 4 => { + out.push_str("f("); + gen_expr(rng, depth.saturating_sub(1), out); + out.push(')'); + } + _ => { + out.push('('); + gen_expr(rng, depth.saturating_sub(1), out); + out.push(')'); + } + } + return; + } + match rng.below(7) { + 0 => { + out.push_str("- "); + gen_expr(rng, depth - 1, out); + } + 1 => { + gen_expr(rng, depth - 1, out); + out.push('['); + gen_expr(rng, depth - 1, out); + out.push(']'); + } + op => { + gen_expr(rng, depth - 1, out); + out.push_str([" ^ ", " * ", " / ", " + ", " - "][op - 2]); + gen_expr(rng, depth - 1, out); + } + } +} + +/// Random items list: `e (as name)? (',' ...)* ';'?`. +fn gen_input(rng: &mut Rng) -> String { + let mut out = String::new(); + let items = 1 + rng.below(3); + for i in 0..items { + if i > 0 { + out.push_str(", "); + } + let depth = 1 + rng.below(4); + gen_expr(rng, depth, &mut out); + match rng.below(3) { + 0 => out.push_str(" as y"), + 1 => out.push_str(" as as"), // alias spelled with the soft keyword + _ => {} + } + } + if rng.below(2) == 0 { + out.push(';'); + } + out +} + +#[test] +fn test_fuzz_valid_expressions() { + let mut rng = Rng(0x5EED_0001); + for _ in 0..400 { + let input = gen_input(&mut rng); + assert_equivalent(&input); + } +} + +#[test] +fn test_fuzz_token_soup() { + const TOKENS: &[&str] = &[ + "x", "1", "as", "+", "-", "*", "/", "^", "(", ")", "[", "]", ",", ";", ".", "f", + ]; + let mut rng = Rng(0x5EED_0002); + for _ in 0..400 { + let len = rng.below(12); + let mut input = String::new(); + for i in 0..len { + if i > 0 { + input.push(' '); + } + input.push_str(TOKENS[rng.below(TOKENS.len())]); + } + assert_equivalent(&input); + } +} + +/// Pinned corners: the soft-keyword collisions that force runtime escapes. +#[test] +fn test_escape_corners() { + for input in [ + "as", // the keyword alone is an expression + "as as as", // expression 'as', aliased to 'as' + "as.as as as", // qualified soft keywords with alias + "a as as, as as a;", // both orders across a list + "x + as as y", // ladder + alias + "f(as) as as", // call arg + alias + "a[as] as x", // index + alias + "- as as as", // prefix + alias + ] { + assert_equivalent(input); + } +} + +/// The static parser must contain a hybrid table (adaptive escapes) and a +/// precedence dispatch; the adaptive twin must contain neither. +#[test] +fn test_generated_shape() { + let stat = include_str!("gen/fuzzexprparser.rs"); + assert!(stat.contains("adaptive escapes"), "expected a hybrid table"); + assert!( + stat.contains("precedence-dispatched"), + "expected a dispatch" + ); + let adap = include_str!("gen/adaptive/fuzzexprparser.rs"); + assert!( + !adap.contains("dfa_predict"), + "adaptive twin must not use tables" + ); +} diff --git a/runtime/Rust/tests/gen/adaptive/fuzzexprbaselistener.rs b/runtime/Rust/tests/gen/adaptive/fuzzexprbaselistener.rs new file mode 100644 index 0000000000..3c91a4c789 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/fuzzexprbaselistener.rs @@ -0,0 +1,83 @@ +// Generated from FuzzExpr.g4 by ANTLR 4.13.2 + +use super::fuzzexprparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by FuzzExprParser. + +pub trait FuzzExprBaseListener<'arena>: + ParseTreeListener<'arena, FuzzExprParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_item(&mut self, _ctx: &ItemContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_item(&mut self, _ctx: &ItemContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_name(&mut self, _ctx: &NameContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_name(&mut self, _ctx: &NameContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_q(&mut self, _ctx: &QContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_q(&mut self, _ctx: &QContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_e(&mut self, _ctx: &EContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_e(&mut self, _ctx: &EContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_atom(&mut self, _ctx: &AtomContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_atom(&mut self, _ctx: &AtomContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/adaptive/fuzzexprlexer.rs b/runtime/Rust/tests/gen/adaptive/fuzzexprlexer.rs new file mode 100644 index 0000000000..60aec0da14 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/fuzzexprlexer.rs @@ -0,0 +1,145 @@ +// Generated from FuzzExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const T__8:i32=9; +pub const T__9:i32=10; +pub const T__10:i32=11; +pub const T__11:i32=12; +pub const T__12:i32=13; +pub const ID:i32=14; +pub const INT:i32=15; +pub const WS:i32=16; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;16] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "ID", "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;14] = [ + None, Some("','"), Some("';'"), Some("'as'"), Some("'.'"), Some("'['"), + Some("']'"), Some("'-'"), Some("'^'"), Some("'*'"), Some("'/'"), Some("'+'"), + Some("'('"), Some("')'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;17] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, None, Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, FuzzExprLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct FuzzExprLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { FuzzExprLexer } +dbt_antlr4::impl_deref! { lexer => FuzzExprLexer } + +impl<'input, 'arena, Input, TF> FuzzExprLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = FuzzExprLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct FuzzExprLexerActions { +} + +impl FuzzExprLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for FuzzExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for FuzzExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "FuzzExprLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 13] = [ + "CAAgmgEMAQQADgAEAg4CBAQOBAQGDgYECA4IBAoOCgQMDgwEDg4OBBAOEAQSDhIEFA4UBBYOFgQYDhgE", + "Gg4aBBwOHAQeDh4CAAIAAgICAgIEAgQCBAIGAgYCCAIIAgoCCgIMAgwCDgIOAhACEAISAhICFAIUAhYC", + "FgIYAhgCGggafBAaFhoYGn4CHAgchgEQHBYcGByIAQIeCB6QARAeFh4YHpIBAh4CHgAAIAICBgQKBg4I", + "EgoWDBoOHhAiEiYUKhYuGDIaNhw6Hj4gAgAGAgDCAfQBAgBgcgYAEhQaGkBAngEAAgIAAAAABgIAAAAA", + "CgIAAAAADgIAAAAAEgIAAAAAFgIAAAAAGgIAAAAAHgIAAAAAIgIAAAAAJgIAAAAAKgIAAAAALgIAAAAA", + "MgIAAAAANgIAAAAAOgIAAAAAPgIAAAACQgIAAAAGRgIAAAAKSgIAAAAOUAIAAAASVAIAAAAWWAIAAAAa", + "XAIAAAAeYAIAAAAiZAIAAAAmaAIAAAAqbAIAAAAucAIAAAAydAIAAAA2egIAAAA6hAECAAAAPo4BAgAA", + "AEJEClgAAEQEAgAAAEZICnYAAEgIAgAAAEpMCsIBAABMTgrmAQAATgwCAAAAUFIKXAAAUhACAAAAVFYK", + "tgEAAFYUAgAAAFhaCroBAABaGAIAAABcXgpaAABeHAIAAABgYgq8AQAAYiACAAAAZGYKVAAAZiQCAAAA", + "aGoKXgAAaigCAAAAbG4KVgAAbiwCAAAAcHIKUAAAcjACAAAAdHYKUgAAdjQCAAAAeHwOAAAAengCAAAA", + "fH4CAAAAfnoCAAAAfoABAgAAAIABOAIAAACCAYYBDgIAAIQBggECAAAAhgGIAQIAAACIAYQBAgAAAIgB", + "igECAAAAigE8AgAAAIwBkAEOBAAAjgGMAQIAAACQAZIBAgAAAJIBjgECAAAAkgGUAQIAAACUAZYBAgAA", + "AJYBmAEMHgAAmAFAAgAAAAgAfogBkgECDAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/adaptive/fuzzexprlistener.rs b/runtime/Rust/tests/gen/adaptive/fuzzexprlistener.rs new file mode 100644 index 0000000000..d70b4e6247 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/fuzzexprlistener.rs @@ -0,0 +1,60 @@ +#![allow(nonstandard_style)] +// Generated from FuzzExpr.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::fuzzexprparser::*; + +pub trait FuzzExprListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, FuzzExprParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link FuzzExprParser#s}. + /// @param ctx the parse tree + fn enter_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#s}. + /// @param ctx the parse tree + fn exit_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#item}. + /// @param ctx the parse tree + fn enter_item<'input: 'arena>(&mut self, _ctx: &ItemContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#item}. + /// @param ctx the parse tree + fn exit_item<'input: 'arena>(&mut self, _ctx: &ItemContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#name}. + /// @param ctx the parse tree + fn enter_name<'input: 'arena>(&mut self, _ctx: &NameContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#name}. + /// @param ctx the parse tree + fn exit_name<'input: 'arena>(&mut self, _ctx: &NameContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#q}. + /// @param ctx the parse tree + fn enter_q<'input: 'arena>(&mut self, _ctx: &QContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#q}. + /// @param ctx the parse tree + fn exit_q<'input: 'arena>(&mut self, _ctx: &QContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#e}. + /// @param ctx the parse tree + fn enter_e<'input: 'arena>(&mut self, _ctx: &EContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#e}. + /// @param ctx the parse tree + fn exit_e<'input: 'arena>(&mut self, _ctx: &EContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#atom}. + /// @param ctx the parse tree + fn enter_atom<'input: 'arena>(&mut self, _ctx: &AtomContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#atom}. + /// @param ctx the parse tree + fn exit_atom<'input: 'arena>(&mut self, _ctx: &AtomContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/adaptive/fuzzexprparser.rs b/runtime/Rust/tests/gen/adaptive/fuzzexprparser.rs new file mode 100644 index 0000000000..04b78d0a83 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/fuzzexprparser.rs @@ -0,0 +1,1208 @@ +// Generated from FuzzExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::fuzzexprlistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const FuzzExpr_T__0:i32=1; +pub const FuzzExpr_T__1:i32=2; +pub const FuzzExpr_T__2:i32=3; +pub const FuzzExpr_T__3:i32=4; +pub const FuzzExpr_T__4:i32=5; +pub const FuzzExpr_T__5:i32=6; +pub const FuzzExpr_T__6:i32=7; +pub const FuzzExpr_T__7:i32=8; +pub const FuzzExpr_T__8:i32=9; +pub const FuzzExpr_T__9:i32=10; +pub const FuzzExpr_T__10:i32=11; +pub const FuzzExpr_T__11:i32=12; +pub const FuzzExpr_T__12:i32=13; +pub const FuzzExpr_ID:i32=14; +pub const FuzzExpr_INT:i32=15; +pub const FuzzExpr_WS:i32=16; +pub const FuzzExpr_EOF:i32=EOF; +pub const RULE_s:usize = 0; +pub const RULE_item:usize = 1; +pub const RULE_name:usize = 2; +pub const RULE_q:usize = 3; +pub const RULE_e:usize = 4; +pub const RULE_atom:usize = 5; +pub const ruleNames: [&'static str; 6] = [ + "s", "item", "name", "q", "e", "atom" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;14] = [ + None, Some("','"), Some("';'"), Some("'as'"), Some("'.'"), Some("'['"), + Some("']'"), Some("'-'"), Some("'^'"), Some("'*'"), Some("'/'"), Some("'+'"), + Some("'('"), Some("')'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;17] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, None, Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, FuzzExprParserExt<'input, 'arena>, FuzzExprParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + FuzzExprParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: FuzzExprListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct FuzzExprTreeWalker; +impl FuzzExprTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: FuzzExprListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, FuzzExprParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum FuzzExprParserNodeKind { + SContext, + ItemContext, + NameContext, + QContext, + EContext, + AtomContext, + Terminal, + Error, +} +pub type FuzzExprParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, FuzzExprParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => FuzzExprParser } +dbt_antlr4::impl_node_kind! { FuzzExprParserNodeKind { +; SContext(enter_s, exit_s, ), ItemContext(enter_item, exit_item, ), NameContext(enter_name, exit_name, ), QContext(enter_q, exit_q, ), EContext(enter_e, exit_e, ), AtomContext(enter_atom, exit_atom, ), + }; listener = dyn FuzzExprListener<'arena, Tok>, +} + +pub struct FuzzExprParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> FuzzExprParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for FuzzExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for FuzzExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "FuzzExpr.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena FuzzExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 4 => FuzzExprParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn e_sempred(_ctx: Option<&'arena EContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 4) + } + 1 => { + recog.precpred(None, 3) + } + 2 => { + recog.precpred(None, 2) + } + 3 => { + recog.precpred(None, 6) + } + _ => true + } + } +} +//------------------- s ---------------- +pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; + +pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::SContext } + fn get_rule_index(&self) -> usize { RULE_s } + fn make_node( + arena: &'arena Arena, + ctx: SContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { + ph: PhantomData + } + ) + } +} + +pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn item_all(&self) -> Vec<&'arena ItemContextAll<'input, 'arena, Tok>>; + fn item(&self, i: usize) -> Option<&'arena ItemContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> SContextAttrs<'input, 'arena, Tok> for SContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn item_all(&self) -> Vec<&'arena ItemContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn item(&self, i: usize) -> Option<&'arena ItemContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == FuzzExpr_EOF) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule item*/ + recog.base.set_state(12); + recog.item()?; + recog.base.set_state(17); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==FuzzExpr_T__0 { + { + { + recog.base.set_state(13); + recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule item*/ + recog.base.set_state(14); + recog.item()?; + } + } + recog.base.set_state(19); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + } + recog.base.set_state(21); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==FuzzExpr_T__1 { + { + recog.base.set_state(20); + recog.base.match_token(FuzzExpr_T__1,&mut recog.err_handler)?; + } + } + + recog.base.set_state(23); + recog.base.match_token(FuzzExpr_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- item ---------------- +pub type ItemContextAll<'input, 'arena, Tok = CommonToken<'input>> = ItemContext<'input, 'arena, Tok>; + +pub type ItemContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ItemContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ItemContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ItemContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::ItemContext } + fn get_rule_index(&self) -> usize { RULE_item } + fn make_node( + arena: &'arena Arena, + ctx: ItemContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ItemContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ItemContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ItemContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ItemContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ItemContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ItemContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ItemContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + fn name(&self) -> Option<&'arena NameContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> ItemContextAttrs<'input, 'arena, Tok> for ItemContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + fn name(&self) -> Option<&'arena NameContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn item(&mut self,) -> Result<&'arena ItemContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(ItemContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_item)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ItemContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(25); + recog.e_rec(0)?; + recog.base.set_state(26); + recog.base.match_token(FuzzExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(27); + recog.name()?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + /*InvokeRule e*/ + recog.base.set_state(29); + recog.e_rec(0)?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- name ---------------- +pub type NameContextAll<'input, 'arena, Tok = CommonToken<'input>> = NameContext<'input, 'arena, Tok>; + +pub type NameContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NameContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct NameContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for NameContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::NameContext } + fn get_rule_index(&self) -> usize { RULE_name } + fn make_node( + arena: &'arena Arena, + ctx: NameContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NameContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => NameContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NameContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut NameContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NameContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, NameContextExt { + ph: PhantomData + } + ) + } +} + +pub trait NameContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> NameContextAttrs<'input, 'arena, Tok> for NameContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == FuzzExpr_ID) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn name(&mut self,) -> Result<&'arena NameContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_name)?; + let _local_ctx_fn = |recog: &Self| -> &'arena NameContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__2 || _la==FuzzExpr_ID) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- q ---------------- +pub type QContextAll<'input, 'arena, Tok = CommonToken<'input>> = QContext<'input, 'arena, Tok>; + +pub type QContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, QContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct QContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for QContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: QContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a QContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => QContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut QContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut QContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, QContextExt { + ph: PhantomData + } + ) + } +} + +pub trait QContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn name_all(&self) -> Vec<&'arena NameContextAll<'input, 'arena, Tok>>; + fn name(&self, i: usize) -> Option<&'arena NameContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> QContextAttrs<'input, 'arena, Tok> for QContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn name_all(&self) -> Vec<&'arena NameContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn name(&self, i: usize) -> Option<&'arena NameContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn q(&mut self,) -> Result<&'arena QContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(QContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_q)?; + let _local_ctx_fn = |recog: &Self| -> &'arena QContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule name*/ + recog.base.set_state(34); + recog.name()?; + recog.base.set_state(39); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + { + { + recog.base.set_state(35); + recog.base.match_token(FuzzExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(36); + recog.name()?; + } + } + } + recog.base.set_state(41); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + } + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- e ---------------- +pub type EContextAll<'input, 'arena, Tok = CommonToken<'input>> = EContext<'input, 'arena, Tok>; + +pub type EContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: EContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, EContextExt { + ph: PhantomData + } + ) + } +} + +pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + fn atom(&self) -> Option<&'arena AtomContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> EContextAttrs<'input, 'arena, Tok> for EContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } + fn atom(&self) -> Option<&'arena AtomContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.e_rec(0) + } + + fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_e, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 8; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(46); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + FuzzExpr_T__6 => { + { + recog.base.set_state(43); + recog.base.match_token(FuzzExpr_T__6,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(44); + recog.e_rec(5)?; + }} + FuzzExpr_T__2 |FuzzExpr_T__11 |FuzzExpr_ID |FuzzExpr_INT => { + { + /*InvokeRule atom*/ + recog.base.set_state(45); + recog.atom()?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(64); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(6,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(62); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(5,&mut recog.base)? { + 1 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + + recog.base.set_state(48); + if !({recog.precpred(None, 4)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; + } + recog.base.set_state(49); + recog.base.match_token(FuzzExpr_T__7,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(50); + recog.e_rec(4)?; + } + } + , + 2 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + + recog.base.set_state(51); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(52); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__8 || _la==FuzzExpr_T__9) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(53); + recog.e_rec(4)?; + } + } + , + 3 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + + recog.base.set_state(54); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(55); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__6 || _la==FuzzExpr_T__10) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(56); + recog.e_rec(3)?; + } + } + , + 4 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + + recog.base.set_state(57); + if !({recog.precpred(None, 6)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; + } + recog.base.set_state(58); + recog.base.match_token(FuzzExpr_T__4,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(59); + recog.e_rec(0)?; + recog.base.set_state(60); + recog.base.match_token(FuzzExpr_T__5,&mut recog.err_handler)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(66); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(6,&mut recog.base)?; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- atom ---------------- +pub type AtomContextAll<'input, 'arena, Tok = CommonToken<'input>> = AtomContext<'input, 'arena, Tok>; + +pub type AtomContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AtomContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct AtomContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AtomContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::AtomContext } + fn get_rule_index(&self) -> usize { RULE_atom } + fn make_node( + arena: &'arena Arena, + ctx: AtomContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AtomContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AtomContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AtomContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AtomContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AtomContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, AtomContextExt { + ph: PhantomData + } + ) + } +} + +pub trait AtomContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> AtomContextAttrs<'input, 'arena, Tok> for AtomContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == FuzzExpr_INT) + } + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == FuzzExpr_ID) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn atom(&mut self,) -> Result<&'arena AtomContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 10, RULE_atom)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AtomContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(86); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(9,&mut recog.base)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule q*/ + recog.base.set_state(67); + recog.q()?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(68); + recog.base.match_token(FuzzExpr_INT,&mut recog.err_handler)?; + } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(69); + recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(70); + recog.e_rec(0)?; + recog.base.set_state(71); + recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; + } + } + , + 4 =>{ + /*------- Outer Most Alt 4 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } + { + recog.base.set_state(73); + recog.base.match_token(FuzzExpr_ID,&mut recog.err_handler)?; + recog.base.set_state(74); + recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; + recog.base.set_state(83); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if (((_la) & !0x3f) == 0 && ((1usize << _la) & 53384) != 0) { + { + /*InvokeRule e*/ + recog.base.set_state(75); + recog.e_rec(0)?; + recog.base.set_state(80); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==FuzzExpr_T__0 { + { + { + recog.base.set_state(76); + recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(77); + recog.e_rec(0)?; + } + } + recog.base.set_state(82); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + } + } + } + + recog.base.set_state(85); + recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 15] = [ + "CAIgsgEEAA4ABAIOAgQEDgQEBg4GBAgOCAQKDgoCAAIAAgAKACAQABQAGAAmEgACAAYALBAAAgACAAIC", + "AgICAgICAgIGAj4QAgIEAgQCBgIGAgYKBkwQBhQGGAZSEgYCCAIIAggCCAYIXhAIAggCCAIIAggCCAII", + "AggCCAIIAggCCAIIAggCCAoIfhAIFAgYCIQBEggCCgIKAgoCCgIKAgoCCgIKAgoCCgIKCgqeARAKFAoY", + "CqQBEgoGCqgBEAoCCgYKrgEQCgIKAAIQDAAECAwQFAAGBAAGBhwcAgASFAQADg4WFsABABgCAAAABDwC", + "AAAACEACAAAADEQCAAAAEFwCAAAAFKwBAgAAABgiBgQCABocCgIAABwgBgQCAB4aAgAAACAmAgAAACIe", + "AgAAACIkAgAAACQqAgAAACYiAgAAACgsCgQAACooAgAAACosAgAAACwuAgAAAC4wCgAAAjACAgAAADI0", + "BhAIADQ2CgYAADY4BggEADg+AgAAADo+BhAIADwyAgAAADw6AgAAAD4GAgAAAEBCDgAAAEIKAgAAAERO", + "BggEAEZICggAAEhMBggEAEpGAgAAAExSAgAAAE5KAgAAAE5QAgAAAFAOAgAAAFJOAgAAAFRWDAgBAFZY", + "Cg4AAFheBhAIClpeBhQKAFxUAgAAAFxaAgAAAF6AAQIAAABgYhQIAABiZAoQAABkfgYQCAhmaBQGAABo", + "ag4CAABqfgYQCAhsbhQEAABucA4EAABwfgYQCAZydBQMAAB0dgoKAAB2eAYQCAB4egoMAAB6fgIAAAB8", + "YAIAAAB8ZgIAAAB8bAIAAAB8cgIAAAB+hAECAAAAgAF8AgAAAIABggECAAAAggESAgAAAIQBgAECAAAA", + "hgGuAQYMBgCIAa4BCh4AAIoBjAEKGAAAjAGOAQYQCACOAZABChoAAJABrgECAAAAkgGUAQocAACUAaYB", + "ChgAAJYBoAEGEAgAmAGaAQoCAACaAZ4BBhAIAJwBmAECAAAAngGkAQIAAACgAZwBAgAAAKABogECAAAA", + "ogGoAQIAAACkAaABAgAAAKYBlgECAAAApgGoAQIAAACoAaoBAgAAAKoBrgEKGgAArAGGAQIAAACsAYgB", + "AgAAAKwBigECAAAArAGSAQIAAACuARYCAAAAFCIqPE5cfIABoAGmAawB" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/fuzzexprbaselistener.rs b/runtime/Rust/tests/gen/fuzzexprbaselistener.rs new file mode 100644 index 0000000000..3c91a4c789 --- /dev/null +++ b/runtime/Rust/tests/gen/fuzzexprbaselistener.rs @@ -0,0 +1,83 @@ +// Generated from FuzzExpr.g4 by ANTLR 4.13.2 + +use super::fuzzexprparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by FuzzExprParser. + +pub trait FuzzExprBaseListener<'arena>: + ParseTreeListener<'arena, FuzzExprParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_item(&mut self, _ctx: &ItemContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_item(&mut self, _ctx: &ItemContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_name(&mut self, _ctx: &NameContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_name(&mut self, _ctx: &NameContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_q(&mut self, _ctx: &QContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_q(&mut self, _ctx: &QContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_e(&mut self, _ctx: &EContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_e(&mut self, _ctx: &EContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_atom(&mut self, _ctx: &AtomContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link FuzzExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_atom(&mut self, _ctx: &AtomContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/fuzzexprlexer.rs b/runtime/Rust/tests/gen/fuzzexprlexer.rs new file mode 100644 index 0000000000..60aec0da14 --- /dev/null +++ b/runtime/Rust/tests/gen/fuzzexprlexer.rs @@ -0,0 +1,145 @@ +// Generated from FuzzExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const T__8:i32=9; +pub const T__9:i32=10; +pub const T__10:i32=11; +pub const T__11:i32=12; +pub const T__12:i32=13; +pub const ID:i32=14; +pub const INT:i32=15; +pub const WS:i32=16; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;16] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "ID", "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;14] = [ + None, Some("','"), Some("';'"), Some("'as'"), Some("'.'"), Some("'['"), + Some("']'"), Some("'-'"), Some("'^'"), Some("'*'"), Some("'/'"), Some("'+'"), + Some("'('"), Some("')'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;17] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, None, Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, FuzzExprLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct FuzzExprLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { FuzzExprLexer } +dbt_antlr4::impl_deref! { lexer => FuzzExprLexer } + +impl<'input, 'arena, Input, TF> FuzzExprLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = FuzzExprLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct FuzzExprLexerActions { +} + +impl FuzzExprLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for FuzzExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for FuzzExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "FuzzExprLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 13] = [ + "CAAgmgEMAQQADgAEAg4CBAQOBAQGDgYECA4IBAoOCgQMDgwEDg4OBBAOEAQSDhIEFA4UBBYOFgQYDhgE", + "Gg4aBBwOHAQeDh4CAAIAAgICAgIEAgQCBAIGAgYCCAIIAgoCCgIMAgwCDgIOAhACEAISAhICFAIUAhYC", + "FgIYAhgCGggafBAaFhoYGn4CHAgchgEQHBYcGByIAQIeCB6QARAeFh4YHpIBAh4CHgAAIAICBgQKBg4I", + "EgoWDBoOHhAiEiYUKhYuGDIaNhw6Hj4gAgAGAgDCAfQBAgBgcgYAEhQaGkBAngEAAgIAAAAABgIAAAAA", + "CgIAAAAADgIAAAAAEgIAAAAAFgIAAAAAGgIAAAAAHgIAAAAAIgIAAAAAJgIAAAAAKgIAAAAALgIAAAAA", + "MgIAAAAANgIAAAAAOgIAAAAAPgIAAAACQgIAAAAGRgIAAAAKSgIAAAAOUAIAAAASVAIAAAAWWAIAAAAa", + "XAIAAAAeYAIAAAAiZAIAAAAmaAIAAAAqbAIAAAAucAIAAAAydAIAAAA2egIAAAA6hAECAAAAPo4BAgAA", + "AEJEClgAAEQEAgAAAEZICnYAAEgIAgAAAEpMCsIBAABMTgrmAQAATgwCAAAAUFIKXAAAUhACAAAAVFYK", + "tgEAAFYUAgAAAFhaCroBAABaGAIAAABcXgpaAABeHAIAAABgYgq8AQAAYiACAAAAZGYKVAAAZiQCAAAA", + "aGoKXgAAaigCAAAAbG4KVgAAbiwCAAAAcHIKUAAAcjACAAAAdHYKUgAAdjQCAAAAeHwOAAAAengCAAAA", + "fH4CAAAAfnoCAAAAfoABAgAAAIABOAIAAACCAYYBDgIAAIQBggECAAAAhgGIAQIAAACIAYQBAgAAAIgB", + "igECAAAAigE8AgAAAIwBkAEOBAAAjgGMAQIAAACQAZIBAgAAAJIBjgECAAAAkgGUAQIAAACUAZYBAgAA", + "AJYBmAEMHgAAmAFAAgAAAAgAfogBkgECDAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/fuzzexprlistener.rs b/runtime/Rust/tests/gen/fuzzexprlistener.rs new file mode 100644 index 0000000000..d70b4e6247 --- /dev/null +++ b/runtime/Rust/tests/gen/fuzzexprlistener.rs @@ -0,0 +1,60 @@ +#![allow(nonstandard_style)] +// Generated from FuzzExpr.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::fuzzexprparser::*; + +pub trait FuzzExprListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, FuzzExprParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link FuzzExprParser#s}. + /// @param ctx the parse tree + fn enter_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#s}. + /// @param ctx the parse tree + fn exit_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#item}. + /// @param ctx the parse tree + fn enter_item<'input: 'arena>(&mut self, _ctx: &ItemContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#item}. + /// @param ctx the parse tree + fn exit_item<'input: 'arena>(&mut self, _ctx: &ItemContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#name}. + /// @param ctx the parse tree + fn enter_name<'input: 'arena>(&mut self, _ctx: &NameContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#name}. + /// @param ctx the parse tree + fn exit_name<'input: 'arena>(&mut self, _ctx: &NameContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#q}. + /// @param ctx the parse tree + fn enter_q<'input: 'arena>(&mut self, _ctx: &QContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#q}. + /// @param ctx the parse tree + fn exit_q<'input: 'arena>(&mut self, _ctx: &QContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#e}. + /// @param ctx the parse tree + fn enter_e<'input: 'arena>(&mut self, _ctx: &EContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#e}. + /// @param ctx the parse tree + fn exit_e<'input: 'arena>(&mut self, _ctx: &EContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link FuzzExprParser#atom}. + /// @param ctx the parse tree + fn enter_atom<'input: 'arena>(&mut self, _ctx: &AtomContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link FuzzExprParser#atom}. + /// @param ctx the parse tree + fn exit_atom<'input: 'arena>(&mut self, _ctx: &AtomContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs new file mode 100644 index 0000000000..060cd64130 --- /dev/null +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -0,0 +1,1233 @@ +// Generated from FuzzExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::fuzzexprlistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const FuzzExpr_T__0:i32=1; +pub const FuzzExpr_T__1:i32=2; +pub const FuzzExpr_T__2:i32=3; +pub const FuzzExpr_T__3:i32=4; +pub const FuzzExpr_T__4:i32=5; +pub const FuzzExpr_T__5:i32=6; +pub const FuzzExpr_T__6:i32=7; +pub const FuzzExpr_T__7:i32=8; +pub const FuzzExpr_T__8:i32=9; +pub const FuzzExpr_T__9:i32=10; +pub const FuzzExpr_T__10:i32=11; +pub const FuzzExpr_T__11:i32=12; +pub const FuzzExpr_T__12:i32=13; +pub const FuzzExpr_ID:i32=14; +pub const FuzzExpr_INT:i32=15; +pub const FuzzExpr_WS:i32=16; +pub const FuzzExpr_EOF:i32=EOF; +pub const RULE_s:usize = 0; +pub const RULE_item:usize = 1; +pub const RULE_name:usize = 2; +pub const RULE_q:usize = 3; +pub const RULE_e:usize = 4; +pub const RULE_atom:usize = 5; +pub const ruleNames: [&'static str; 6] = [ + "s", "item", "name", "q", "e", "atom" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;14] = [ + None, Some("','"), Some("';'"), Some("'as'"), Some("'.'"), Some("'['"), + Some("']'"), Some("'-'"), Some("'^'"), Some("'*'"), Some("'/'"), Some("'+'"), + Some("'('"), Some("')'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;17] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, None, Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, FuzzExprParserExt<'input, 'arena>, FuzzExprParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + FuzzExprParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: FuzzExprListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct FuzzExprTreeWalker; +impl FuzzExprTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: FuzzExprListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, FuzzExprParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum FuzzExprParserNodeKind { + SContext, + ItemContext, + NameContext, + QContext, + EContext, + AtomContext, + Terminal, + Error, +} +pub type FuzzExprParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, FuzzExprParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => FuzzExprParser } +dbt_antlr4::impl_node_kind! { FuzzExprParserNodeKind { +; SContext(enter_s, exit_s, ), ItemContext(enter_item, exit_item, ), NameContext(enter_name, exit_name, ), QContext(enter_q, exit_q, ), EContext(enter_e, exit_e, ), AtomContext(enter_atom, exit_atom, ), + }; listener = dyn FuzzExprListener<'arena, Tok>, +} + +pub struct FuzzExprParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> FuzzExprParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for FuzzExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for FuzzExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "FuzzExpr.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena FuzzExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 4 => FuzzExprParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn e_sempred(_ctx: Option<&'arena EContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 4) + } + 1 => { + recog.precpred(None, 3) + } + 2 => { + recog.precpred(None, 2) + } + 3 => { + recog.precpred(None, 6) + } + _ => true + } + } +} +//------------------- s ---------------- +pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; + +pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::SContext } + fn get_rule_index(&self) -> usize { RULE_s } + fn make_node( + arena: &'arena Arena, + ctx: SContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { + ph: PhantomData + } + ) + } +} + +pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn item_all(&self) -> Vec<&'arena ItemContextAll<'input, 'arena, Tok>>; + fn item(&self, i: usize) -> Option<&'arena ItemContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> SContextAttrs<'input, 'arena, Tok> for SContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn item_all(&self) -> Vec<&'arena ItemContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn item(&self, i: usize) -> Option<&'arena ItemContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == FuzzExpr_EOF) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule item*/ + recog.base.set_state(12); + recog.item()?; + recog.base.set_state(17); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==FuzzExpr_T__0 { + { + { + recog.base.set_state(13); + recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule item*/ + recog.base.set_state(14); + recog.item()?; + } + } + recog.base.set_state(19); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + } + recog.base.set_state(21); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==FuzzExpr_T__1 { + { + recog.base.set_state(20); + recog.base.match_token(FuzzExpr_T__1,&mut recog.err_handler)?; + } + } + + recog.base.set_state(23); + recog.base.match_token(FuzzExpr_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- item ---------------- +pub type ItemContextAll<'input, 'arena, Tok = CommonToken<'input>> = ItemContext<'input, 'arena, Tok>; + +pub type ItemContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ItemContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ItemContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ItemContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::ItemContext } + fn get_rule_index(&self) -> usize { RULE_item } + fn make_node( + arena: &'arena Arena, + ctx: ItemContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ItemContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ItemContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ItemContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ItemContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ItemContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ItemContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ItemContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + fn name(&self) -> Option<&'arena NameContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> ItemContextAttrs<'input, 'arena, Tok> for ItemContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + fn name(&self) -> Option<&'arena NameContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn item(&mut self,) -> Result<&'arena ItemContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(ItemContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_item)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ItemContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } } { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(25); + recog.e_rec(0)?; + recog.base.set_state(26); + recog.base.match_token(FuzzExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(27); + recog.name()?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + /*InvokeRule e*/ + recog.base.set_state(29); + recog.e_rec(0)?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- name ---------------- +pub type NameContextAll<'input, 'arena, Tok = CommonToken<'input>> = NameContext<'input, 'arena, Tok>; + +pub type NameContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NameContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct NameContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for NameContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::NameContext } + fn get_rule_index(&self) -> usize { RULE_name } + fn make_node( + arena: &'arena Arena, + ctx: NameContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NameContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => NameContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NameContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut NameContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NameContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, NameContextExt { + ph: PhantomData + } + ) + } +} + +pub trait NameContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> NameContextAttrs<'input, 'arena, Tok> for NameContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == FuzzExpr_ID) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn name(&mut self,) -> Result<&'arena NameContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_name)?; + let _local_ctx_fn = |recog: &Self| -> &'arena NameContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__2 || _la==FuzzExpr_ID) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- q ---------------- +pub type QContextAll<'input, 'arena, Tok = CommonToken<'input>> = QContext<'input, 'arena, Tok>; + +pub type QContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, QContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct QContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for QContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: QContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a QContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => QContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut QContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut QContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, QContextExt { + ph: PhantomData + } + ) + } +} + +pub trait QContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn name_all(&self) -> Vec<&'arena NameContextAll<'input, 'arena, Tok>>; + fn name(&self, i: usize) -> Option<&'arena NameContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> QContextAttrs<'input, 'arena, Tok> for QContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn name_all(&self) -> Vec<&'arena NameContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn name(&self, i: usize) -> Option<&'arena NameContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn q(&mut self,) -> Result<&'arena QContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(QContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_q)?; + let _local_ctx_fn = |recog: &Self| -> &'arena QContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule name*/ + recog.base.set_state(34); + recog.name()?; + recog.base.set_state(39); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + { + { + recog.base.set_state(35); + recog.base.match_token(FuzzExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(36); + recog.name()?; + } + } + } + recog.base.set_state(41); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + } + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- e ---------------- +pub type EContextAll<'input, 'arena, Tok = CommonToken<'input>> = EContext<'input, 'arena, Tok>; + +pub type EContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: EContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, EContextExt { + ph: PhantomData + } + ) + } +} + +pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + fn atom(&self) -> Option<&'arena AtomContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> EContextAttrs<'input, 'arena, Tok> for EContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } + fn atom(&self) -> Option<&'arena AtomContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.e_rec(0) + } + + fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_e, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 8; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(46); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + FuzzExpr_T__6 => { + { + recog.base.set_state(43); + recog.base.match_token(FuzzExpr_T__6,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(44); + recog.e_rec(5)?; + }} + FuzzExpr_T__2 |FuzzExpr_T__11 |FuzzExpr_ID |FuzzExpr_INT => { + { + /*InvokeRule atom*/ + recog.base.set_state(45); + recog.atom()?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(64); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(62); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } } { + 1 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + + recog.base.set_state(48); + if !({recog.precpred(None, 4)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; + } + recog.base.set_state(49); + recog.base.match_token(FuzzExpr_T__7,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(50); + recog.e_rec(4)?; + } + } + , + 2 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + + recog.base.set_state(51); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(52); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__8 || _la==FuzzExpr_T__9) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(53); + recog.e_rec(4)?; + } + } + , + 3 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + + recog.base.set_state(54); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(55); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__6 || _la==FuzzExpr_T__10) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(56); + recog.e_rec(3)?; + } + } + , + 4 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + + recog.base.set_state(57); + if !({recog.precpred(None, 6)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; + } + recog.base.set_state(58); + recog.base.match_token(FuzzExpr_T__4,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(59); + recog.e_rec(0)?; + recog.base.set_state(60); + recog.base.match_token(FuzzExpr_T__5,&mut recog.err_handler)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(66); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } }; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- atom ---------------- +pub type AtomContextAll<'input, 'arena, Tok = CommonToken<'input>> = AtomContext<'input, 'arena, Tok>; + +pub type AtomContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AtomContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct AtomContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AtomContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = FuzzExprParserNodeKind; + fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::AtomContext } + fn get_rule_index(&self) -> usize { RULE_atom } + fn make_node( + arena: &'arena Arena, + ctx: AtomContext<'input, 'arena, Tok>, + ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AtomContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AtomContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AtomContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AtomContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AtomContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, AtomContextExt { + ph: PhantomData + } + ) + } +} + +pub trait AtomContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> AtomContextAttrs<'input, 'arena, Tok> for AtomContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == FuzzExpr_INT) + } + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == FuzzExpr_ID) + } +} + +impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn atom(&mut self,) -> Result<&'arena AtomContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 10, RULE_atom)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AtomContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(86); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(9)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(9,&mut recog.base)? } else { _sdp } } { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule q*/ + recog.base.set_state(67); + recog.q()?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(68); + recog.base.match_token(FuzzExpr_INT,&mut recog.err_handler)?; + } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(69); + recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(70); + recog.e_rec(0)?; + recog.base.set_state(71); + recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; + } + } + , + 4 =>{ + /*------- Outer Most Alt 4 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } + { + recog.base.set_state(73); + recog.base.match_token(FuzzExpr_ID,&mut recog.err_handler)?; + recog.base.set_state(74); + recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; + recog.base.set_state(83); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if (((_la) & !0x3f) == 0 && ((1usize << _la) & 53384) != 0) { + { + /*InvokeRule e*/ + recog.base.set_state(75); + recog.e_rec(0)?; + recog.base.set_state(80); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==FuzzExpr_T__0 { + { + { + recog.base.set_state(76); + recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(77); + recog.e_rec(0)?; + } + } + recog.base.set_state(82); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + } + } + } + + recog.base.set_state(85); + recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +// the serialized ATN is followed by 9 static SLL prediction tables (-Xstatic-dfa): +// decision 6: precedence-dispatched over cutoffs [2, 3, 4, 6], tables [4 5 6 7 8] +// decision 2: LL(*) cyclic, 32 states, 15 adaptive escapes +// decision 3: LL(k), k=1, 10 states +// decision 5: LL(k), k=1, 5 states +// decision 9: LL(k), k=2, 15 states +// table 4 (decision 6): LL(k), k=1, 9 states +// table 5 (decision 6): LL(k), k=1, 10 states +// table 6 (decision 6): LL(k), k=1, 10 states +// table 7 (decision 6): LL(k), k=1, 9 states +// table 8 (decision 6): LL(k), k=0, 1 states +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 29] = [ + "CAIgsgEEAA4ABAIOAgQEDgQEBg4GBAgOCAQKDgoCAAIAAgAKACAQABQAGAAmEgACAAYALBAAAgACAAIC", + "AgICAgICAgIGAj4QAgIEAgQCBgIGAgYKBkwQBhQGGAZSEgYCCAIIAggCCAYIXhAIAggCCAIIAggCCAII", + "AggCCAIIAggCCAIIAggCCAoIfhAIFAgYCIQBEggCCgIKAgoCCgIKAgoCCgIKAgoCCgIKCgqeARAKFAoY", + "CqQBEgoGCqgBEAoCCgYKrgEQCgIKAAIQDAAECAwQFAAGBAAGBhwcAgASFAQADg4WFsABABgCAAAABDwC", + "AAAACEACAAAADEQCAAAAEFwCAAAAFKwBAgAAABgiBgQCABocCgIAABwgBgQCAB4aAgAAACAmAgAAACIe", + "AgAAACIkAgAAACQqAgAAACYiAgAAACgsCgQAACooAgAAACosAgAAACwuAgAAAC4wCgAAAjACAgAAADI0", + "BhAIADQ2CgYAADY4BggEADg+AgAAADo+BhAIADwyAgAAADw6AgAAAD4GAgAAAEBCDgAAAEIKAgAAAERO", + "BggEAEZICggAAEhMBggEAEpGAgAAAExSAgAAAE5KAgAAAE5QAgAAAFAOAgAAAFJOAgAAAFRWDAgBAFZY", + "Cg4AAFheBhAIClpeBhQKAFxUAgAAAFxaAgAAAF6AAQIAAABgYhQIAABiZAoQAABkfgYQCAhmaBQGAABo", + "ag4CAABqfgYQCAhsbhQEAABucA4EAABwfgYQCAZydBQMAAB0dgoKAAB2eAYQCAB4egoMAAB6fgIAAAB8", + "YAIAAAB8ZgIAAAB8bAIAAAB8cgIAAAB+hAECAAAAgAF8AgAAAIABggECAAAAggESAgAAAIQBgAECAAAA", + "hgGuAQYMBgCIAa4BCh4AAIoBjAEKGAAAjAGOAQYQCACOAZABChoAAJABrgECAAAAkgGUAQocAACUAaYB", + "ChgAAJYBoAEGEAgAmAGaAQoCAACaAZ4BBhAIAJwBmAECAAAAngGkAQIAAACgAZwBAgAAAKABogECAAAA", + "ogGoAQIAAACkAaABAgAAAKYBlgECAAAApgGoAQIAAACoAaoBAgAAAKoBrgEKGgAArAGGAQIAAACsAYgB", + "AgAAAKwBigECAAAArAGSAQIAAACuARYCAAAAFCIqPE5cfIABoAGmAawBChIUBEDOAwAAAQEAAAQEBAIA", + "AAABAAEBAAAAAQEAAAEBAQEBAQEBAAQAAAQEAAAAAAAAAAAAAAAAAAQAAAQEAAAAAAAAAAAAHkhISHic", + "AZwBnAGcAZwBqAHGAeQB5AH8AfwB/AGaAqwC4gLiAuICngPOA84DzgPOA84DzgPOA84DzgMGBgIODgQY", + "GAYcHAgeHgoBAQwCAg4EBBAGBhIICBQKChYOFhgBAQwCAg4EBBAGBhIICBQKChYOFhgYGBoBAQwCAg4E", + "BBAGBhIKChYOFhgGBgIcHAIGBhwODh4YGCAcHCIeHiQGBiYODigYGCocHCweHi4ICDAKCjIMDAoOFjQI", + "CDAKCjIMDAoOFjQYGDYKCjIMDAoOFjQBAQwCAg4EBBAGBhIICDgKCjoODhgQFDwWFhgBAQwCAg4EBBAG", + "BhIICDgKCjoODhgQFDwWFhgYGD4BAQwCAg4EBBAGBhIKCjoODhgQFDwWFhgGFDYABAQEBAIEBAQEBAAA", + "AAAAAAAAAAA2NjY2NjY2NjY2AQECAgIEBAQGBgYICAgKCgoMDAwODhYQGhoSCgoeAAgGAgQAAAAAAAAe", + "Hh4eHgoKAg4OBBAQBhIUCBYWBBIeVAACBgAEAgICAgICAgIIAgAAAAIAAAAAAAAAAAAAAAAYGBhUVFRU", + "VFRUVFRUVFQGBgIYGAQcHAYeHggBAQoCAgwEBA4GBhAICBIKChQMDBYOFhgYGBoaGhwBEjAABAQEBAIE", + "AgQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICgoKDAwMDhYOGhoQARQ8AAQEBAQCBAQCBAQA", + "AAAAAAAAAAAAPDw8PDw8PDw8PAEBAgICBAQEBgYGCAoKCgwMDA4ODhAUEBYWDhoaEgEUPAAEBAQEAgQE", + "AgQEAAAAAAAAAAAAADw8PDw8PDw8PDwBAQICAgQEBAYGBggKCgoMDAwODg4QEBASFg4aGhIBEjAABAQE", + "BAIEBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICgoKDAwMDhYOGhoQAQIABAAAAAIMCAQG", + "CAwICgwOEA==" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/lrdfaparser.rs b/runtime/Rust/tests/gen/lrdfaparser.rs index b1a2266283..9b6b97213c 100644 --- a/runtime/Rust/tests/gen/lrdfaparser.rs +++ b/runtime/Rust/tests/gen/lrdfaparser.rs @@ -1334,14 +1334,14 @@ where recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); recog.base.set_state(38); recog.err_handler.sync(&mut recog.base)?; - _alt = recog.base.dfa_predict(2)?; + _alt = { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } }; while { _alt!=2 && _alt!=INVALID_ALT } { if _alt==1 { recog.trigger_exit_rule_event()?; { recog.base.set_state(36); recog.err_handler.sync(&mut recog.base)?; - match recog.base.dfa_predict(1)? { + match { let _sdp = recog.base.dfa_predict(1)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(1,&mut recog.base)? } else { _sdp } } { 1 =>{ { /*recRuleLabeledAltStartAction*/ @@ -1488,7 +1488,7 @@ where } recog.base.set_state(40); recog.err_handler.sync(&mut recog.base)?; - _alt = recog.base.dfa_predict(2)?; + _alt = { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } }; } } Ok(()) @@ -1525,7 +1525,7 @@ static _serializedATN: [&'static str; 13] = [ "AAAYFgIAAAAaTAIAAAAcHhQMAAAeIAoKAAAgSgYEAgwiJBQKAAAkJg4AAAAmSgYEAgwoKhQIAAAqLA4C", "AAAsSgYEAgouMBQGAAAwMgoSAAAyNAYEAgA0NgoUAAA2OAYEAgY4SgIAAAA6PBQSAAA8PgoCAAA+QAYE", "AgBAQgoEAABCSgIAAABERhQQAABGSgoGAABIHAIAAABIIgIAAABIKAIAAABILgIAAABIOgIAAABIRAIA", - "AABKUAIAAABMSAIAAABMTgIAAABOBgIAAABQTAIAAAAGGEhMCBAGAg4qAAoMBgIECAAAAAAAAAAAKioq", + "AABKUAIAAABMSAIAAABMTgIAAABOBgIAAABQTAIAAAAGGEhMChAGAg4qAAoMBgIECAAAAAAAAAAAKioq", "KioqKgICAgYGBAgIBgoKCAwOChAQBhISDAEQKgAEAgQCAgIEBAAAAAAAAAAAKioqKioqKioBAQICAgQE", "BAYGBggIEAoSEgwUFA4BECoABAIEAgIEBAQAAAAAAAAAACoqKioqKioqAQECAgIEBAQGBgYICBAKEhIM", "FBQOARI2AAQCBAIEAgQEBAAAAAAAAAAAADY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBAQChISDhQU", diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index d8c780180b..c4d9d4a164 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -588,7 +588,7 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(23); recog.err_handler.sync(&mut recog.base)?; - match recog.base.dfa_predict(0)? { + match { let _sdp = recog.base.dfa_predict(0)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(0,&mut recog.base)? } else { _sdp } } { 1 =>{ /*------- Outer Most Alt 1 -------*/ recog.base.with_mut_ctx(|ctx| { @@ -946,7 +946,7 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(30); recog.err_handler.sync(&mut recog.base)?; - match recog.base.dfa_predict(1)? { + match { let _sdp = recog.base.dfa_predict(1)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(1,&mut recog.base)? } else { _sdp } } { 1 =>{ /*------- Outer Most Alt 1 -------*/ recog.base.with_mut_ctx(|ctx| { @@ -1206,7 +1206,7 @@ where { recog.base.set_state(44); recog.err_handler.sync(&mut recog.base)?; - _alt = recog.base.dfa_predict(3)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; while { _alt!=2 && _alt!=INVALID_ALT } { if _alt==1 { { @@ -1220,7 +1220,7 @@ where } recog.base.set_state(46); recog.err_handler.sync(&mut recog.base)?; - _alt = recog.base.dfa_predict(3)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; } recog.base.set_state(47); recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; @@ -1341,7 +1341,7 @@ where } recog.base.set_state(54); recog.err_handler.sync(&mut recog.base)?; - _alt = recog.base.dfa_predict(4)?; + _alt = { let _sdp = recog.base.dfa_predict(4)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(4,&mut recog.base)? } else { _sdp } }; if _alt==2 || _alt==INVALID_ALT { break } } recog.base.set_state(56); @@ -1445,7 +1445,7 @@ where { recog.base.set_state(61); recog.err_handler.sync(&mut recog.base)?; - match recog.base.dfa_predict(5)? { + match { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } } { x if x == 1 =>{ { recog.base.set_state(59); @@ -1758,7 +1758,7 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(70); recog.err_handler.sync(&mut recog.base)?; - match recog.base.dfa_predict(6)? { + match { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } } { 1 =>{ /*------- Outer Most Alt 1 -------*/ recog.base.with_mut_ctx(|ctx| { @@ -1827,7 +1827,7 @@ static _serializedATN: [&'static str; 14] = [ "AAAAWFQCAAAAWFoCAAAAWl4CAAAAXFgCAAAAXmAKEAAAYGIKFAAAYg4CAAAAZGYKEAAAZmoKEgAAaGQC", "AAAAamwCAAAAbGgCAAAAbG4CAAAAbnACAAAAcHIKEAAAcnQKFAAAdBICAAAAdngKEAAAeHwKEgAAenYC", "AAAAenwCAAAAfH4CAAAAfoABChAAAIABggEKFAAAggEWAgAAAIQBhgEKFgAAhgGOAQoYAACIAYoBChYA", - "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEIDA4AChgAAAYCBAAAAAAAAAwY", + "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEKDA4AChgAAAYCBAAAAAAAAAwY", "GBgYAgICCAgEBAQGBgYIAgoeAAAEAgAABAAAAAAGGBgYHhoaAgEBBAoKBg4OCBoaAgYIEgAAAgQAAAAA", "AAYSEhIQEAISEgQUFAYICBIAAAIEAAAAAAAGEhISEBACEhIEFBQGCggSAAACBAAAAAAABhISEhAQAhIS", "BBQUBgwGDAAAAgAAAAAGDAwWFgIYGAQA" diff --git a/runtime/Rust/tests/lr_dfa_tests.rs b/runtime/Rust/tests/lr_dfa_tests.rs index 280c09d61e..54382543b9 100644 --- a/runtime/Rust/tests/lr_dfa_tests.rs +++ b/runtime/Rust/tests/lr_dfa_tests.rs @@ -150,13 +150,16 @@ fn test_errors_still_reported() { } /// The operator loop of the left-recursive rule must be table-driven: no -/// adaptive_predict call sites anywhere in the generated parser. +/// bare adaptive_predict call sites anywhere in the generated parser (the +/// only occurrences are the hybrid-escape fallbacks inlined at each +/// table-driven site, dead code for this grammar's escape-free tables). #[test] fn test_no_adaptive_predict_in_generated_code() { let src = include_str!("gen/lrdfaparser.rs"); - assert!( - !src.contains("adaptive_predict"), - "grammars/LrDfa.g4 must generate zero adaptive_predict call sites" + assert_eq!( + src.matches("adaptive_predict(").count(), + src.matches("if _sdp == INVALID_ALT").count(), + "grammars/LrDfa.g4 must generate zero bare adaptive_predict call sites" ); assert!( src.contains("precedence-dispatched"), diff --git a/runtime/Rust/tests/static_dfa_tests.rs b/runtime/Rust/tests/static_dfa_tests.rs index 9f96b61a95..9c593e359d 100644 --- a/runtime/Rust/tests/static_dfa_tests.rs +++ b/runtime/Rust/tests/static_dfa_tests.rs @@ -151,12 +151,17 @@ fn test_no_viable_alt_handling() { } } -/// The generated parser must contain zero adaptive_predict call sites. +/// The generated parser must contain zero bare adaptive_predict call +/// sites: every prediction goes through dfa_predict, and the only +/// adaptive_predict occurrences are the hybrid-escape fallbacks inlined at +/// each table-driven site (dead code for this grammar's escape-free +/// tables). #[test] fn test_no_adaptive_predict_in_generated_code() { let src = include_str!("gen/staticdfaparser.rs"); - assert!( - !src.contains("adaptive_predict"), + assert_eq!( + src.matches("adaptive_predict(").count(), + src.matches("if _sdp == INVALID_ALT").count(), "StaticDFA parser should be fully table-driven" ); assert!( diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index 755ba37540..3a3b1af49c 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -770,7 +770,11 @@ loop { // carried inside the serialized ATN blob (see SerializedBase64ATN) and // decoded together with the ATN into its static_dfas field. -staticDFAPredict(choice) ::= ".base.dfa_predict()?" +// The static-table prediction with the hybrid-escape fallback: a table may +// return INVALID_ALT to defer the prediction (an escape state of a partial +// table, or a precedence class without a table); the decision then reruns +// through adaptive_predict - sound because dfa_predict never consumes input. +staticDFAPredict(choice) ::= "{ let _sdp = .base.dfa_predict()?; if _sdp == INVALID_ALT { .get_interpreter().adaptive_predict(,&mut .base)? } else { _sdp } }" DFAAltBlock(choice, preamble, alts, error) ::= << .base.set_state(); diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 5885c7d8a3..ec1b8a4cc5 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -105,7 +105,21 @@ public enum Category { /** The precedence loop decision of a left-recursive rule; stays on adaptivePredict. */ LR_PRECEDENCE, /** DFA construction exceeded {@link #maxDfaStates}. */ - OVERFLOW + OVERFLOW, + /** + * A partial (depth- and size-bounded) static DFA with escape states: + * lookahead prefixes the table fully proves are predicted + * statically; everything else - untrusted conflicts, and the + * frontier beyond the depth/size budget - reaches an escape state, + * where the walker defers to {@code adaptivePredict} (which rescans + * from the decision start; the table never consumes input). + * Behavior-preserving by construction: the table only + * short-circuits what it proved, the reference engine handles the + * rest. This serves the hot paths of decisions whose complete SLL + * DFA is impractically large (unbounded phantom-FOLLOW scans) or + * contains genuinely context-sensitive corners. + */ + HYBRID } public static class Result { @@ -143,6 +157,19 @@ public static class Result { public PrecedenceStaticDFA precDfa; /** For LR_PRECEDENCE decisions: report detail (per-class outcomes). */ public String precNote; + /** For HYBRID tables: number of escape states. */ + public int escapes; + /** + * For HYBRID tables: fraction of the start state's outgoing token + * space whose successor subgraph contains at least one accept + * state - i.e., the share of first tokens for which the table can + * complete some predictions (typically the short-lookahead + * majority; longer scans down the same edges escape). A static + * proxy for hot-path coverage: edges that lead exclusively to + * escapes contribute nothing and a table whose start state resolves + * nothing is pure overhead. + */ + public double coverage; public Result(DecisionState decisionState) { this.decisionState = decisionState; @@ -208,6 +235,23 @@ public Result(DecisionState decisionState) { /** Hard cap on DFA states per decision (per construction attempt). */ public int maxDfaStates = 2000; + /** + * Hybrid-table construction bounds (see {@link Category#HYBRID}): the + * lookahead depth beyond which states become escapes, and the state + * budget after which the remaining frontier becomes escapes. The work + * queue is FIFO, so construction is breadth-first by lookahead depth + * and the emitted prefix is exactly the shallowest - hottest - states. + */ + public int hybridDepthCap = 4; + public int hybridStateCap = 64; + /** + * Minimum start-state coverage (see {@link Result#coverage}) for a + * hybrid table to be worth its size: below this, nearly every + * prediction would escape to adaptivePredict anyway and the table is + * pure overhead. + */ + public double hybridMinCoverage = 0.1; + /** * Iterative-deepening schedule for the calling-context depth bound. The * first attempt is exact (widening only at direct call-site recursion, @@ -267,6 +311,13 @@ public Result(DecisionState decisionState) { protected int precRuleIndex = -1; /** During precedence-mode construction: exact conflicts are not trusted. */ protected boolean trustExactAmbig = true; + /** + * When true, {@link #buildDFA} builds a bounded hybrid table: untrusted + * conflicts and the frontier beyond {@link #hybridDepthCap}/ + * {@link #hybridStateCap} become escape states instead of failing the + * decision (see {@link Category#HYBRID}). + */ + protected boolean hybridMode; /** * Lazily built: state number of a rule call's follow state - the state * grammar-wide FOLLOW links from the callee's stop state point back to - @@ -308,17 +359,45 @@ public Result classify(DecisionState s) { } // iterative deepening: exact first, then progressively wider approximation - Result last = res; + Result outcome = res; + boolean allOverflowed = true; for (int depthBound : wideningDepths) { Result attempt = new Result(s); attempt.wideningDepth = depthBound; if (!buildDFA(s, attempt, depthBound)) { - return attempt; + outcome = attempt; + allOverflowed = false; + break; } - last = attempt; + outcome = attempt; + } + if (allOverflowed) outcome.category = Category.OVERFLOW; + + // full construction failed: try a bounded hybrid table (exact + // contexts; the depth cap keeps it small) whose escape states defer + // untrusted conflicts and the deep frontier to adaptivePredict + if (outcome.dfa == null + && (outcome.category == Category.OVERFLOW + || outcome.category == Category.CONTEXT_SENSITIVE)) { + Result hybrid = classifyHybrid(s); + if (hybrid != null && hybrid.dfa != null) return hybrid; } - last.category = Category.OVERFLOW; - return last; + return outcome; + } + + /** One hybrid construction attempt; null if it overflowed (can't happen + * in practice: the depth/state caps bound it) or found predicates. */ + protected Result classifyHybrid(DecisionState s) { + Result hybrid = new Result(s); + hybrid.wideningDepth = Integer.MAX_VALUE; + this.hybridMode = true; + try { + if (buildDFA(s, hybrid, Integer.MAX_VALUE)) return null; + } + finally { + this.hybridMode = false; + } + return hybrid; } /** @@ -390,23 +469,11 @@ protected Result classifyPrecedence(DecisionState s) { ci++; } - if (callByFollowState == null) { - callByFollowState = new HashMap(); - for (ATNState st : atn.states) { - if (st == null) continue; - for (int i = 0; i < st.getNumberOfTransitions(); i++) { - Transition t = st.transition(i); - if (t instanceof RuleTransition) { - RuleTransition rt = (RuleTransition)t; - callByFollowState.put(rt.followState.stateNumber, rt); - } - } - } - } + callByFollowState(); StaticDFA[] tables = new StaticDFA[reps.length]; StringBuilder note = new StringBuilder(); - boolean allStatic = true; + boolean anyTable = false; int maxK = 0; int totalStates = 0; this.precRuleIndex = s.ruleIndex; @@ -421,6 +488,19 @@ protected Result classifyPrecedence(DecisionState s) { if (!buildDFA(s, a, depthBound)) { attempt = a; break; } attempt = a; // overflow at this bound; try tighter widening } + if (attempt.dfa == null && !attempt.sawPredicate) { + // full construction failed for this class: bounded + // hybrid table with adaptive escapes + Result h = new Result(s); + h.wideningDepth = Integer.MAX_VALUE; + this.hybridMode = true; + try { + if (!buildDFA(s, h, Integer.MAX_VALUE)) attempt = h; + } + finally { + this.hybridMode = false; + } + } res.sawPrecPredicate |= attempt.sawPrecPredicate; res.usedWidening |= attempt.usedWidening; if (note.length() > 0) note.append(' '); @@ -428,8 +508,12 @@ protected Result classifyPrecedence(DecisionState s) { : c < cutoffs.length ? "=" + (cutoffs[c-1]+1) + ".." + cutoffs[c] : ">" + cutoffs[cutoffs.length-1]).append(':'); if (attempt.dfa == null) { - allStatic = false; - note.append(attempt.category); + if (attempt.category == Category.HYBRID) { + // hybrid construction worked but fell below the + // coverage floor; the class stays adaptive + note.append(String.format("adaptive(cover=%.0f%%)", attempt.coverage*100)); + } + else note.append(attempt.category); if (!attempt.contextSensitiveConflicts.isEmpty()) { note.append("/ctx").append(distinct(attempt.contextSensitiveConflicts)); } @@ -439,13 +523,19 @@ protected Result classifyPrecedence(DecisionState s) { if (!attempt.exactAmbigConflicts.isEmpty()) { note.append("/exact").append(distinct(attempt.exactAmbigConflicts)); } - if (abortOnUntrustedConflict) break; } else { + anyTable = true; tables[c] = attempt.dfa; maxK = Math.max(maxK, attempt.k); totalStates += attempt.numDfaStates; - note.append(attempt.dfa.cyclic ? "LL(*)" : "k=" + attempt.k); + if (attempt.category == Category.HYBRID) { + note.append(String.format("hyb(cover=%.0f%%)", attempt.coverage*100)); + res.escapes += attempt.escapes; + } + else { + note.append(attempt.dfa.cyclic ? "LL(*)" : "k=" + attempt.k); + } } } } @@ -456,7 +546,10 @@ protected Result classifyPrecedence(DecisionState s) { } res.precNote = "classes=" + reps.length + " [" + note + "]"; - if (allStatic) { + if (anyTable) { + // classes without a table dispatch to adaptivePredict (their + // dispatch entry is -1); the group is worthwhile as long as any + // class predicts statically res.precDfa = new PrecedenceStaticDFA(s.decision, cutoffs, tables); res.k = maxK; res.numDfaStates = totalStates; @@ -464,6 +557,78 @@ protected Result classifyPrecedence(DecisionState s) { return res; } + /** Lazily built {@link #callByFollowState}. */ + protected Map callByFollowState() { + if (callByFollowState == null) { + callByFollowState = new HashMap(); + for (ATNState st : atn.states) { + if (st == null) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + callByFollowState.put(rt.followState.stateNumber, rt); + } + } + } + } + return callByFollowState; + } + + /** + * Evaluate a precedence guard {@code precpred(n)} of rule {@code rule} + * against the precedence the rule was entered with in this closure + * path, when that value is statically known - and it usually is: the + * top return state of the configuration's context identifies the call + * site (it is the follow state of the {@link RuleTransition} that + * entered the rule), and the transition carries the call's constant + * precedence argument. Depth-bounded widening preserves the immediate + * return frame, so the evaluation stays available at every widening + * level except the fully context-free approximation. + * + *

Returns null when the entry precedence is unknown or ambiguous: + * empty/wildcard context (the decision's own frame, or a phantom frame + * entered by popping through the decision boundary), a wildcard among + * the tops of a merged context, or merged tops with disagreeing guard + * outcomes. Callers must then fall back to assumed-true traversal with + * {@link #PRECPRED_TAINT} - the evaluation only ever prunes paths whose + * guard provably fails.

+ * + *

Why pruning is behavior-preserving:

+ *
    + *
  • Against the parse: a lookahead path through a false precedence + * guard is unparseable - the generated code checks the guard and fails. + * Pruning removes no real parse.
  • + *
  • Against {@code adaptivePredict}, which traverses these guards as + * pure epsilon (it evaluates precedence predicates only in frame 0 of a + * precedence DFA start state) and therefore keeps the pruned paths: the + * left-recursion transform's guards only restrict which + * derivation produces a token string, never the strings + * themselves. A phantom "consume this operator in a deeper frame" path + * is duplicated, token for token and with the same alternative at the + * decision under construction, by the legal path that exits the deeper + * frames (loop exits are unguarded) and consumes the operator at an + * outer loop level whose weaker guard admits it. So the pruned closure + * computes the same prefix-to-viable-alternatives map, just without + * enumerating the redundant derivations that blow up the configuration + * space in precedence ladders.
  • + *
+ */ + protected Boolean evalPrecpredFromContext(PredictionContext ctx, int rule, int n) { + if (ctx == null || ctx.isEmpty()) return null; + Boolean agreed = null; + for (int i = 0; i < ctx.size(); i++) { + int returnState = ctx.getReturnState(i); + if (returnState == PredictionContext.EMPTY_RETURN_STATE) return null; + RuleTransition call = callByFollowState().get(returnState); + if (call == null || call.target.ruleIndex != rule) return null; + boolean outcome = n >= call.precedence; + if (agreed == null) agreed = outcome; + else if (agreed != outcome) return null; + } + return agreed; + } + /** * Tool-side port of ParserATNSimulator#applyPrecedenceFilter, applied to * the merged start configuration set of a precedence class before it @@ -534,6 +699,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List> edgeLabels = new ArrayList>(); List acceptAlts = new ArrayList(); // 0 = not an accept state List fallbackAlts = new ArrayList(); // 0 = none + List stateDepth = new ArrayList(); // lookahead depth (BFS layer) Set start = new LinkedHashSet(); Set startBusy = new HashSet(); @@ -553,6 +719,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { edgeLabels.add(new ArrayList()); acceptAlts.add(0); fallbackAlts.add(0); + stateDepth.add(0); Deque work = new ArrayDeque(); work.add(0); @@ -606,6 +773,11 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { // both runtime SLL and full-context LL acceptAlts.set(d, conflicting.nextSetBit(0)); } + else if (hybridMode) { + // the conflict cannot be resolved statically: defer + // this state to adaptivePredict + acceptAlts.set(d, StaticDFA.ESCAPE); + } else if (abortOnUntrustedConflict) { // not a trusted exact ambiguity: no widening level can // make this decision table-eligible @@ -616,6 +788,15 @@ else if (abortOnUntrustedConflict) { continue; } + if (hybridMode + && (stateDepth.get(d) >= hybridDepthCap || states.size() >= hybridStateCap)) { + // beyond the depth/size budget: don't expand, defer to + // adaptivePredict (BFS order makes this the deep, cold + // frontier - the shallow hot states are already built) + acceptAlts.set(d, StaticDFA.ESCAPE); + continue; + } + // Error-avoidance fallback for this (expanding) state: the // minimum alternative that already "finished the decision entry // rule" (popped through the decision boundary). When prediction @@ -644,6 +825,7 @@ else if (abortOnUntrustedConflict) { edgeLabels.add(new ArrayList()); acceptAlts.add(0); fallbackAlts.add(0); + stateDepth.add(stateDepth.get(d)+1); work.add(id); } edges.get(d).add(id); @@ -653,10 +835,15 @@ else if (abortOnUntrustedConflict) { res.numDfaStates = states.size(); if (overflow) { + if (System.getProperty("antlr.dfa.debug") != null) { + dumpOverflowStats(s, states, depthBound); + } res.category = Category.OVERFLOW; return true; } if (res.sawPredicate) { + // user predicates gate viability in ways the table cannot + // represent; not eligible even for a hybrid table res.category = Category.PREDICATED; return false; } @@ -664,6 +851,22 @@ else if (abortOnUntrustedConflict) { boolean cyclic = isCyclic(edges); if (!cyclic) res.k = longestPath(edges); + int escapes = 0; + for (int a : acceptAlts) { + if (a == StaticDFA.ESCAPE) escapes++; + } + if (escapes > 0) { + // hybrid table: emit only if the start state itself resolves + // something - a start-state escape means nothing is decidable + res.category = Category.HYBRID; + res.escapes = escapes; + res.coverage = startCoverage(edges, edgeLabels, acceptAlts); + if (acceptAlts.get(0) != StaticDFA.ESCAPE && res.coverage >= hybridMinCoverage) { + res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, fallbackAlts, cyclic, res.k); + } + return false; + } + if (!res.contextSensitiveConflicts.isEmpty() || !res.approxConflicts.isEmpty()) { res.category = Category.CONTEXT_SENSITIVE; } @@ -678,6 +881,89 @@ else if (abortOnUntrustedConflict) { return false; } + /** + * Hot-path coverage proxy of a hybrid table: the fraction of the start + * state's outgoing token space whose successor subgraph contains at + * least one accept state. An edge leading exclusively to escapes (a + * conflict right behind it at every depth) contributes nothing - the + * table can never resolve a prediction down that path; an edge whose + * subgraph mixes accepts and escapes resolves its short-lookahead + * prefixes (typically the dynamic majority) and escapes the rest. + */ + protected static double startCoverage(List> edges, + List> edgeLabels, + List acceptAlts) { + int n = edges.size(); + // reverse reachability from accept states + List> reverse = new ArrayList>(n); + for (int i = 0; i < n; i++) reverse.add(new ArrayList()); + for (int sIdx = 0; sIdx < n; sIdx++) { + for (int target : edges.get(sIdx)) reverse.get(target).add(sIdx); + } + boolean[] reachesAccept = new boolean[n]; + Deque work = new ArrayDeque(); + for (int i = 0; i < n; i++) { + if (acceptAlts.get(i) > 0) { + reachesAccept[i] = true; + work.add(i); + } + } + while (!work.isEmpty()) { + for (int prev : reverse.get(work.remove())) { + if (!reachesAccept[prev]) { + reachesAccept[prev] = true; + work.add(prev); + } + } + } + long total = 0, useful = 0; + List startEdges = edges.get(0); + List startLabels = edgeLabels.get(0); + for (int e = 0; e < startEdges.size(); e++) { + int width = startLabels.get(e).size(); + total += width; + if (reachesAccept[startEdges.get(e)]) useful += width; + } + return total == 0 ? 0 : (double)useful/total; + } + + /** Diagnostics for overflowing decisions (-Dantlr.dfa.debug): where the + * configuration population concentrates, and its taint composition. */ + private void dumpOverflowStats(DecisionState s, List> states, int depthBound) { + Map ruleHisto = new HashMap(); + int totalConfigs = 0, emptyCtx = 0, precTainted = 0, widenedTainted = 0, boundary = 0; + int maxSetSize = 0; + for (Set set : states) { + maxSetSize = Math.max(maxSetSize, set.size()); + for (ATNConfig c : set) { + totalConfigs++; + String rn = g.getRule(c.state.ruleIndex).name; + ruleHisto.merge(rn, 1, Integer::sum); + if (c.context == null || c.context.isEmpty()) emptyCtx++; + if ((c.reachesIntoOuterContext & PRECPRED_TAINT) != 0) precTainted++; + if ((c.reachesIntoOuterContext & WIDENED_TAINT) != 0) widenedTainted++; + if ((c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0) boundary++; + } + } + List> top = new ArrayList>(ruleHisto.entrySet()); + top.sort((a, b) -> b.getValue() - a.getValue()); + StringBuilder sb = new StringBuilder(); + sb.append("OVERFLOW-DEBUG d=").append(s.decision) + .append(" depthBound=").append(depthBound) + .append(" states=").append(states.size()) + .append(" configs=").append(totalConfigs) + .append(" maxSet=").append(maxSetSize) + .append(" emptyCtx=").append(emptyCtx) + .append(" precTaint=").append(precTainted) + .append(" widened=").append(widenedTainted) + .append(" boundary=").append(boundary) + .append("\n top rules: "); + for (int i = 0; i < Math.min(8, top.size()); i++) { + sb.append(top.get(i).getKey()).append('=').append(top.get(i).getValue()).append(' '); + } + System.err.println(sb); + } + /** Serialize the recorded DFA into the flat table form used by codegen. */ protected static StaticDFA toStaticDFA(int decision, List> edgeLabels, @@ -915,6 +1201,7 @@ else if (contextDepth(config.context) >= currentDepthBound closure(callee, configs, busy, res, depth >= 0 ? depth+1 : depth); } else if (t instanceof PrecedencePredicateTransition) { + int n = ((PrecedencePredicateTransition)t).precedence; if (precStartClosure && depth == 0) { // Frame-0 guard of the precedence decision under // construction: evaluate precpred(n) = n >= p against @@ -922,18 +1209,32 @@ else if (t instanceof PrecedencePredicateTransition) { // precedence DFA start-state computation (pass 1 of // applyPrecedenceFilter). Failing configs are // eliminated; passing ones continue untainted. - if (((PrecedencePredicateTransition)t).precedence >= precEvalValue) { + if (n >= precEvalValue) { closure(new ATNConfig(config, t.target), configs, busy, res, depth); } } else { - // traversed as epsilon = assumed true, matching the - // runtime, which only evaluates precedence predicates - // in frame 0 of a precedence DFA start state - res.sawPrecPredicate = true; - ATNConfig c2 = new ATNConfig(config, t.target); - c2.reachesIntoOuterContext |= PRECPRED_TAINT; - closure(c2, configs, busy, res, depth); + // Deeper guard: evaluate against the constant precedence + // the enclosing rule was entered with, when the context + // identifies it (see evalPrecpredFromContext, including + // the argument for why the pruning is behavior- + // preserving even though adaptivePredict traverses these + // guards as epsilon). Unknown entry precedence falls + // back to the runtime's own treatment - assumed true - + // tainted as an over-approximation. + Boolean outcome = evalPrecpredFromContext(config.context, p.ruleIndex, n); + if (outcome != null) { + if (outcome) { + closure(new ATNConfig(config, t.target), configs, busy, res, depth); + } + // else: guard provably fails; path pruned + } + else { + res.sawPrecPredicate = true; + ATNConfig c2 = new ATNConfig(config, t.target); + c2.reachesIntoOuterContext |= PRECPRED_TAINT; + closure(c2, configs, busy, res, depth); + } } } else if (t instanceof PredicateTransition) { @@ -1153,6 +1454,11 @@ public static String report(Grammar g) { buf.append(String.format("%-22s d=%-4d %-17s", rule.name, r.decisionState.decision, r.category)); if (r.k >= 0) buf.append(" k=").append(r.k); buf.append(" dfaStates=").append(r.numDfaStates); + if (r.category == Category.HYBRID) { + buf.append(" escapes=").append(r.escapes) + .append(String.format(" cover=%.0f%%", r.coverage*100)) + .append(r.dfa == null ? " [adaptive]" : ""); + } if (!r.exactAmbigConflicts.isEmpty()) { buf.append(" exactAmbigAlts=").append(distinct(r.exactAmbigConflicts)); } diff --git a/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java b/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java index 61df1d5fb5..3ebd07ac08 100644 --- a/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java +++ b/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java @@ -35,7 +35,11 @@ public class PrecedenceStaticDFA { public final int decision; /** Sorted distinct precedence-guard constants; class(p) = |{c : c < p}|. */ public final int[] cutoffs; - /** One table per precedence class; length {@code cutoffs.length + 1}. */ + /** + * One table per precedence class; length {@code cutoffs.length + 1}. + * A null entry means the class has no static table (not even a hybrid + * one) and dispatches straight to {@code adaptivePredict}. + */ public final StaticDFA[] tables; public PrecedenceStaticDFA(int decision, int[] cutoffs, StaticDFA[] tables) { diff --git a/tool/src/org/antlr/v4/analysis/StaticDFA.java b/tool/src/org/antlr/v4/analysis/StaticDFA.java index 6cf9281f91..104a183227 100644 --- a/tool/src/org/antlr/v4/analysis/StaticDFA.java +++ b/tool/src/org/antlr/v4/analysis/StaticDFA.java @@ -27,9 +27,17 @@ * -1); a lookahead token matching no edge means no viable alternative.

*/ public class StaticDFA { + /** + * Sentinel in {@link #accepts}: an escape state of a hybrid table. The + * walker stops and defers the whole prediction to + * {@code adaptivePredict} (the table never consumes input, so the + * rescan is trivially sound). See DecisionClassifier's HYBRID category. + */ + public static final int ESCAPE = -1; + public final int decision; public final int numStates; - /** Predicted alternative per state; 0 = not an accept state. */ + /** Predicted alternative per state; 0 = not an accept state; {@link #ESCAPE} = escape. */ public final int[] accepts; /** * Error-avoidance fallback per state; 0 = none. When prediction dies at diff --git a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java index 725dc50cce..e5dfc2d523 100644 --- a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java +++ b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java @@ -36,7 +36,8 @@ * decision (-1: referenced only via a dispatch below) * numStates * numEdgeInts - * accepts[numStates] (predicted alt per state; 0 = non-accept) + * accepts[numStates] (predicted alt per state; 0 = non-accept; + * -1 = escape: defer to adaptivePredict) * fallbacks[numStates] (error-avoidance alt per state; 0 = none) * edgeOffsets[numStates+1] (index of each state's first edge int) * edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) @@ -45,14 +46,15 @@ * decision * numCutoffs * cutoffs[numCutoffs] (sorted; class(p) = #cutoffs < p) - * tableIndex[numCutoffs+1] (table of each precedence class) + * tableIndex[numCutoffs+1] (table of each precedence class; + * -1 = class dispatches to adaptivePredict) * * *

Identical class tables are deduplicated by content and shared through * their table index.

*/ public class SerializedStaticDFAs extends OutputModelObject { - public static final int FORMAT_VERSION = 4; + public static final int FORMAT_VERSION = 5; public final int numTables; /** Base64 text segments of the serialized blob, one rendered per line. */ @@ -106,11 +108,17 @@ public static int appendIntStream(Map dfas, +", tables"); for (int c = 0; c < group.tables.length; c++) { StaticDFA t = group.tables[c]; - int idx = indexOf(tables, t); - if (idx < 0) { - idx = tables.size(); - tables.add(t); - tableDecisions.add(-1); + int idx; + if (t == null) { + idx = -1; // class dispatches to adaptivePredict + } + else { + idx = indexOf(tables, t); + if (idx < 0) { + idx = tables.size(); + tables.add(t); + tableDecisions.add(-1); + } } entry[2 + group.cutoffs.length + c] = idx; comment.append(c == 0 ? " [" : " ").append(idx); @@ -133,10 +141,15 @@ public static int appendIntStream(Map dfas, for (int v : dfa.fallbacks) data.add(v); for (int v : dfa.edgeOffsets) data.add(v); for (int v : dfa.edges) data.add(v); + int escapes = 0; + for (int v : dfa.accepts) { + if (v == StaticDFA.ESCAPE) escapes++; + } comments.add((tableDecisions.get(i) >= 0 ? "decision "+dfa.decision : "table "+i+" (decision "+dfa.decision+")") +": "+(dfa.cyclic ? "LL(*) cyclic" : "LL(k), k="+dfa.maxK) - +", "+dfa.numStates+" states"); + +", "+dfa.numStates+" states" + +(escapes > 0 ? ", "+escapes+" adaptive escapes" : "")); } data.add(dispatches.size()); for (int[] entry : dispatches) { From c59e6fb1adf00ad4d0137a1f1b68e69a1f4798a9 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Mon, 13 Jul 2026 03:45:36 -0400 Subject: [PATCH 07/48] Class-aware boundary pops and enter/exit resolution for precedence tables Diagnosis of why simple arithmetic (SELECT 1 + 1) stayed on the adaptive path while multi-column selects got their speedup: every prediction was table-first, but the hot class-0 states of the operator loops escaped. Two independent causes, both fixed: 1. Escape-by-truncation: the hybrid state budget starved sibling states of wide first ranks, so single-token predictions - the dynamic majority - escaped on sheer decision fanout. Depth 0/1 states are now exempt from the state cap (rank 1 is bounded by the token alphabet); the cap applies from depth 2. 2. Escape-by-phantom-conflict: the loop's exit alternative popped into grammar-wide FOLLOW, where a phantom enclosing loop with assumed-true guards could always eat the operator, manufacturing an enter/exit conflict on every operator token. Addressed on two fronts: - Boundary pops from the decision's own frame (depth >= 0) now chase only call sites whose precedence argument lies in the class interval - the only invocations the class table serves. Pops from phantom enclosing frames (depth < 0) still chase everything: the closure busy set is keyed by lineage (pre/post boundary) so the filtered first pop cannot swallow the unfiltered deeper pop of an identical configuration (that dedup once dropped the exit-two- loops-then-BETWEEN-takes-the-AND derivations). Entry invocations of the left-recursive rule itself (no caller frame) defer to adaptivePredict at runtime - the tables deliberately prune the empty-stack FOLLOW space such invocations predict against. - Class-0 enter/exit exact conflicts resolve statically to iterate by a substitution argument: an exit derivation whose scanned tokens are consumed by an enclosing invocation of the same loop maps to an iterate derivation of the identical sentence (all guards pass at class-0 entry precedences), so exit never becomes uniquely viable and the adaptive engine answers iterate whenever it terminates. Trust requires: exactness (config pairing - the dangling shapes fail it), no FOREIGN_CONSUME taint on exit (a new taint marking post-pop consumption outside the loop block without a loop frame in context: the genuinely context-sensitive BETWEEN e AND e collision is foreign and keeps escaping), and no unmet obligation in any phantom same-rule frame (a new epsilon- completability check: a plain binary loop is completable right after its operand, but expr (',' expr)* '>>' expr still owes its '>>', and there the runtime kills iterate with deeper lookahead - caught by the ReturnValueAndActionsList descriptors). Assumed-true precedence guards (PRECPRED taint) no longer block exact-ambiguity trust in plain decisions: the runtime's own SLL closure traverses non-frame-0 precedence predicates as epsilon under the same assumption, so such configs mirror the runtime; only widening remains an analysis-only artifact. Both unsoundness candidates in the development of this change were caught by differential tests (B4 escape corners, runtime suite), and the final form passes all of them. Rust runtime: dfa_predict escape tracing behind ANTLR_DFA_TRACE (OnceLock-cached), is_precedence_dispatched + entry-frame defer; Java runtime: same defer in Parser.dfaPredict. Measured on Trino (Rust, 30k parses each): - SELECT T1.C1, T2.C2, T3.C3, T4.C4 FROM MY_TABLE: 17.6us -> 3.8us (4.6x) - SELECT 1 + 1 FROM MY_TABLE: one residual escape (class-0 operator conflict where phantom foreign/obligated exit paths remain possible), ~parity with adaptive - operator-loop classes now 98-100% coverage across all six SQL grammars, all LR loops static, zero bare adaptive call sites, OVERFLOW/CONTEXT_SENSITIVE still zero Verified: cargo tests incl. fuzz differential (53), runtime suites 707/707, tool-testsuite 694, B4 17/17 escape corners, p1probe 24/24, lrdfa 8/8. Signed-off-by: Bo Lin --- .../Java/src/org/antlr/v4/runtime/Parser.java | 8 + .../antlr/v4/runtime/atn/StaticDFATables.java | 12 + runtime/Rust/src/parser.rs | 38 +- runtime/Rust/src/static_dfa.rs | 11 + runtime/Rust/tests/gen/lrdfaparser.rs | 17 +- .../antlr/v4/analysis/DecisionClassifier.java | 337 +++++++++++++++++- 6 files changed, 392 insertions(+), 31 deletions(-) diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java index d521d8d8e4..f7fb8e7ae8 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java @@ -546,6 +546,14 @@ public Token getCurrentToken() { public int dfaPredict(StaticDFATables tables, int decision) throws RecognitionException { + if ( tables.isPrecedenceDispatched(decision) && _ctx.getParent()==null ) { + // The left-recursive rule is itself the parse entry (no caller + // frame): per-precedence-class tables are built against the + // rule's compatible call sites, but an entry invocation pops + // into the grammar-wide FOLLOW space instead - only the + // adaptive engine models that. + return getInterpreter().adaptivePredict(_input, decision, _ctx); + } // the precedence selects the table of dispatched decisions (the // operator loops of left-recursive rules); plain decisions ignore it int table = tables.tableFor(decision, getPrecedence()); diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java index 297d46c68a..835d044770 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java @@ -145,6 +145,18 @@ public static StaticDFATables deserialize(String[] segments) { * defers the whole prediction to {@code adaptivePredict}. */ public static final int ESCAPE = -1; + /** + * Is {@code decision} precedence-dispatched (per-precedence-class + * tables of a left-recursive loop)? Such tables are built against the + * decision rule's compatible call sites and must not be consulted when + * the left-recursive rule itself is the parse entry (no caller frame): + * the adaptive engine then explores every FOLLOW link from the empty + * stack, a behavior the class tables deliberately prune. + */ + public boolean isPrecedenceDispatched(int decision) { + return decisionToTable[decision] <= -2; + } + /** * The table serving {@code decision}: {@code precedence} (the parser's * current precedence, i.e. the top of its precedence stack) selects the diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index adffbcfda8..2b8e14f351 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -484,17 +484,33 @@ where /// consumes input). A lookahead token matching no table edge produces a /// `NoViableAlt` error anchored at the decision start token, matching /// `adaptive_predict`'s convention. + /// Diagnostic escape tracing for `dfa_predict` (`ANTLR_DFA_TRACE=1`): + /// logs every prediction the static tables defer to the adaptive + /// engine, the tool for finding which decisions a given input keeps + /// escaping on. Checked once per process. + fn dfa_trace() -> bool { + static TRACE: std::sync::OnceLock = std::sync::OnceLock::new(); + *TRACE.get_or_init(|| std::env::var_os("ANTLR_DFA_TRACE").is_some()) + } + pub fn dfa_predict(&mut self, decision: i32) -> Result { // the precedence selects the table of dispatched decisions (the // operator loops of left-recursive rules); plain decisions ignore it let precedence = self.get_precedence(); - let Some(dfa) = self - .atn_manager - .atn() - .static_dfas - .table(decision, precedence) - else { + let static_dfas = &self.atn_manager.atn().static_dfas; + if static_dfas.is_precedence_dispatched(decision) && self.parent_ctx().is_none() { + // The left-recursive rule is itself the parse entry (no caller + // frame): per-precedence-class tables are built against the + // rule's compatible call sites, but an entry invocation pops + // into the grammar-wide FOLLOW space instead - only the + // adaptive engine models that. + return Ok(crate::atn::INVALID_ALT); + } + let Some(dfa) = static_dfas.table(decision, precedence) else { // this precedence class has no static table + if Self::dfa_trace() { + eprintln!("DFA-TRACE no-table d={} prec={}", decision, precedence); + } return Ok(crate::atn::INVALID_ALT); }; let mut s = 0usize; @@ -504,6 +520,16 @@ where // hybrid-table escape: the caller reruns the prediction // through the adaptive engine (no input was consumed, so // the rescan starts clean) + if Self::dfa_trace() { + eprintln!( + "DFA-TRACE escape d={} prec={} state={} depth={} la1={}", + decision, + precedence, + s, + i - 1, + self.input.la(1) + ); + } return Ok(crate::atn::INVALID_ALT); } if let Some(alt) = dfa.accept(s) { diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs index 0f9896527b..6da8a93710 100644 --- a/runtime/Rust/src/static_dfa.rs +++ b/runtime/Rust/src/static_dfa.rs @@ -183,6 +183,17 @@ impl StaticDFATables { } } + /// Is the decision precedence-dispatched (per-precedence-class tables + /// of a left-recursive loop)? Such tables are built against the + /// decision rule's compatible call sites and must not be consulted + /// when the left-recursive rule itself is the parse entry (no caller + /// frame): the adaptive engine then explores every FOLLOW link from + /// the empty stack, a behavior the class tables deliberately prune. + #[inline] + pub fn is_precedence_dispatched(&self, decision: i32) -> bool { + self.decision_to_table[decision as usize] <= -2 + } + /// The table for a decision; `precedence` (the parser's current /// precedence, i.e. the top of its precedence stack) selects the /// precedence class of dispatched decisions and is ignored for plain diff --git a/runtime/Rust/tests/gen/lrdfaparser.rs b/runtime/Rust/tests/gen/lrdfaparser.rs index 9b6b97213c..1c1bba2f9c 100644 --- a/runtime/Rust/tests/gen/lrdfaparser.rs +++ b/runtime/Rust/tests/gen/lrdfaparser.rs @@ -1509,16 +1509,16 @@ where // decision 2: precedence-dispatched over cutoffs [3, 4, 5, 6, 8, 9], tables [1 2 3 4 5 6 7] // decision 1: LL(k), k=1, 7 states // table 1 (decision 2): LL(k), k=1, 8 states -// table 2 (decision 2): LL(k), k=1, 8 states +// table 2 (decision 2): LL(k), k=1, 5 states // table 3 (decision 2): LL(k), k=1, 9 states -// table 4 (decision 2): LL(k), k=1, 9 states +// table 4 (decision 2): LL(k), k=1, 5 states // table 5 (decision 2): LL(k), k=1, 8 states -// table 6 (decision 2): LL(k), k=1, 7 states +// table 6 (decision 2): LL(k), k=1, 3 states // table 7 (decision 2): LL(k), k=0, 1 states static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); -static _serializedATN: [&'static str; 13] = [ +static _serializedATN: [&'static str; 12] = [ "CAIaVAQADgAEAg4CAgACAAIAAgICAgICAgICAgYCGhACAgICAgICAgICAgICAgICAgICAgICAgICAgIC", "AgICAgICAgICAgICAgICAgIKAkoQAhQCGAJQEgICAgACBAQABAAEAgAMDgQACAgQEF4ACAIAAAAEGAIA", "AAAICgYEAgAKDAoAAAIMAgIAAAAOEAwCAQAQEgoIAAASGgYEAg4UGgoWAAAWGgoYAAAYDgIAAAAYFAIA", @@ -1527,9 +1527,8 @@ static _serializedATN: [&'static str; 13] = [ "AgBAQgoEAABCSgIAAABERhQQAABGSgoGAABIHAIAAABIIgIAAABIKAIAAABILgIAAABIOgIAAABIRAIA", "AABKUAIAAABMSAIAAABMTgIAAABOBgIAAABQTAIAAAAGGEhMChAGAg4qAAoMBgIECAAAAAAAAAAAKioq", "KioqKgICAgYGBAgIBgoKCAwOChAQBhISDAEQKgAEAgQCAgIEBAAAAAAAAAAAKioqKioqKioBAQICAgQE", - "BAYGBggIEAoSEgwUFA4BECoABAIEAgIEBAQAAAAAAAAAACoqKioqKioqAQECAgIEBAQGBgYICBAKEhIM", - "FBQOARI2AAQCBAIEAgQEBAAAAAAAAAAAADY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBAQChISDhQU", - "EAESNgAEAgQCBAIEBAQAAAAAAAAAAAA2NjY2NjY2NjYBAQICAgQEBAYGBggICAoKCgwMEAoSEg4UFBAB", - "ECoABAIEAgQEBAQAAAAAAAAAACoqKioqKioqAQECAgIEBAQGBgYICBAKEhIMFBQOAQ4kAAQCBAQEBAQA", - "AAAAAAAAJCQkJCQkJAEBAgICBAQGBggQCBISChQUDAECAAQAAAACBAwGCAoMEBICBAYICgwO" + "BAYGBggIEAoSEgwUFA4BChgABAICAgQAAAAAABgYGBgYAQECAgIEBgYGCBAIARI2AAQCBAIEAgQEBAAA", + "AAAAAAAAADY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBAQChISDhQUEAEKGAAEAgICBAAAAAAAGBgY", + "GBgBAQICAgQGBgYKCggBECoABAIEAgQEBAQAAAAAAAAAACoqKioqKioqAQECAgIEBAQGBgYICBAKEhIM", + "FBQOAQYMAAQCBAAAAAwMDAEBAgICBAECAAQAAAACBAwGCAoMEBICBAYICgwO" ]; \ No newline at end of file diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index ec1b8a4cc5..b3f5765ce6 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -226,6 +226,23 @@ public Result(DecisionState decisionState) { */ protected static final int PRECPRED_TAINT = 2; + /** + * Taint for configurations that, after popping through the decision + * boundary of the left-recursive rule under a per-precedence-class + * construction, consumed a token outside the rule's operator loop - + * i.e. not at a loop-block state and without a loop-block frame in the + * calling context (an operand descent). Such consumption is + * "foreign": the phantom outer context eating the tokens is not an + * enclosing invocation of the same loop, so the enter/exit + * substitution argument (see {@link #classifyPrecedence}) does not + * apply and the conflict must escape to the adaptive engine. The + * genuinely context-sensitive shapes - e.g. {@code BETWEEN e AND e} + * colliding with a boolean {@code AND} loop, where the phantom + * consumer is a primary alternative of the rule, not its loop - are + * exactly the foreign ones. + */ + protected static final int FOREIGN_CONSUME_TAINT = 8; + /** Taint for configurations whose calling context was widened. */ protected static final int WIDENED_TAINT = 4; @@ -307,6 +324,58 @@ public Result(DecisionState decisionState) { protected boolean precStartClosure; /** Representative precedence of the class under construction. */ protected int precEvalValue; + + /** + * Inclusive entry-precedence bounds of the precedence class under + * construction (see {@link #classifyPrecedence}). A class's table is + * only ever consulted for invocations whose entry precedence lies in + * this interval, and the entry precedence is exactly the precedence + * argument of the invoking call site. The closure uses the bounds to + * restrict decision-boundary pops to the compatible call sites: the + * runtime pops with the real stack, which is always such a call site, + * so the restriction prunes only phantom paths (an over-approximation + * artifact), never a runtime-reachable derivation. The one exception - + * invoking the left-recursive rule itself as the parse entry, where the + * runtime chases every FOLLOW link from the empty stack - is handled by + * the generated call site, which defers entry-frame invocations to + * adaptivePredict (see the {@code isEntry} parameter of dfaPredict). + */ + protected int precClassLo, precClassHi; + + /** + * ATN states of the operator loop block of the left-recursive rule + * under per-precedence-class construction (the star-loop entry's + * iterate branch, rule-local: operand rule references contribute + * their follow states, not their bodies). Token consumption at these + * states - or in a rule invoked from them (a loop-block return state + * in the calling context) - is "loop consumption"; everything else a + * boundary-popped config consumes is foreign (see + * {@link #FOREIGN_CONSUME_TAINT}). + */ + protected java.util.BitSet precLoopStates; + + /** + * ATN states of the precedence rule from which its stop state is + * reachable by epsilon transitions alone (rule references block: a + * pending operand or operator is an unmet obligation). A phantom + * enclosing frame of the enter/exit substitution argument must carry + * no such obligation at resolution time - a plain binary operator + * loop is completable right after its operand, but a compound + * alternative like {@code expr (',' expr)* '>>' expr} still owes its + * {@code '>>'} after a comma operand, and there the runtime can kill + * the iterate alternative with deeper lookahead and legitimately + * predict exit. + */ + protected java.util.BitSet precCompletableStates; + + /** + * True while building the lowest precedence class (class 0). The + * enter/exit substitution argument requires every operator guard of + * the rule to pass at the class's entry precedences, which holds for + * class 0 by construction (its upper bound is the smallest guard + * constant) and for no other class. + */ + protected boolean precClassSubstitutable; /** Rule index of the precedence decision under construction; -1 = none. */ protected int precRuleIndex = -1; /** During precedence-mode construction: exact conflicts are not trusted. */ @@ -471,6 +540,55 @@ protected Result classifyPrecedence(DecisionState s) { callByFollowState(); + // The operator loop block: rule-local BFS along the iterate branch + // of the star-loop entry (transition 0); rule references contribute + // their follow states (operand bodies are foreign rules reached + // with a loop-block frame in the context instead). The exit branch + // (transition 1) and everything past it stay outside. + this.precLoopStates = new java.util.BitSet(); + Deque loopWork = new ArrayDeque(); + loopWork.add(s.transition(0).target); + ATNState loopExit = s.transition(1).target; + while (!loopWork.isEmpty()) { + ATNState st = loopWork.remove(); + if (st == loopExit || st.ruleIndex != s.ruleIndex + || st instanceof RuleStopState + || precLoopStates.get(st.stateNumber)) { + continue; + } + precLoopStates.set(st.stateNumber); + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + loopWork.add(t instanceof RuleTransition + ? ((RuleTransition)t).followState : t.target); + } + } + + // Epsilon-completability (see precCompletableStates): fixpoint over + // reverse epsilon edges from the rule's stop state. + this.precCompletableStates = new java.util.BitSet(); + RuleStopState stop = atn.ruleToStopState[s.ruleIndex]; + precCompletableStates.set(stop.stateNumber); + boolean changed = true; + while (changed) { + changed = false; + for (ATNState st : atn.states) { + if (st == null || st.ruleIndex != s.ruleIndex + || precCompletableStates.get(st.stateNumber)) { + continue; + } + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t.isEpsilon() && !(t instanceof RuleTransition) + && precCompletableStates.get(t.target.stateNumber)) { + precCompletableStates.set(st.stateNumber); + changed = true; + break; + } + } + } + } + StaticDFA[] tables = new StaticDFA[reps.length]; StringBuilder note = new StringBuilder(); boolean anyTable = false; @@ -481,6 +599,9 @@ protected Result classifyPrecedence(DecisionState s) { try { for (int c = 0; c < reps.length; c++) { this.precEvalValue = reps[c]; + this.precClassLo = reps[c]; + this.precClassHi = c < cutoffs.length ? cutoffs[c] : Integer.MAX_VALUE; + this.precClassSubstitutable = c == 0; Result attempt = null; for (int depthBound : wideningDepths) { Result a = new Result(s); @@ -702,7 +823,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List stateDepth = new ArrayList(); // lookahead depth (BFS layer) Set start = new LinkedHashSet(); - Set startBusy = new HashSet(); + Set startBusy = new HashSet(); this.precStartClosure = precRuleIndex >= 0; for (int i = 0; i < s.getNumberOfTransitions(); i++) { closure(new ATNConfig(s.transition(i).target, i+1, EmptyPredictionContext.Instance), @@ -713,6 +834,15 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { start = applyPrecedenceFilter(start); } start = canonical(start); + if (precRuleIndex >= 0 && "full".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("PREC-START d=%d rep=%d [%d,%d] configs:%n", + s.decision, precEvalValue, precClassLo, precClassHi); + for (ATNConfig c : start) { + System.err.printf(" alt=%d rule=%s state=%d taint=%d supp=%s ctx=%s%n", + c.alt, g.getRule(c.state.ruleIndex).name, c.state.stateNumber, + c.reachesIntoOuterContext, c.isPrecedenceFilterSuppressed(), c.context); + } + } stateIds.put(start, 0); states.add(start); edges.add(new ArrayList()); @@ -742,16 +872,72 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { Collection altSubsets = PredictionMode.getConflictingAltSubsets(cs); boolean exact = PredictionMode.allSubsetsConflict(altSubsets) && PredictionMode.allSubsetsEqual(altSubsets); - boolean hardTainted = false; + boolean widenedTainted = false; boolean anyBoundary = false; boolean allBoundary = true; for (ATNConfig c : cs) { - if ((c.reachesIntoOuterContext & HARD_TAINT) != 0) hardTainted = true; + if ((c.reachesIntoOuterContext & WIDENED_TAINT) != 0) widenedTainted = true; if ((c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0) anyBoundary = true; else allBoundary = false; } + BitSet conflicting = PredictionMode.getAlts(altSubsets); + + // Enter/exit ambiguity of a class-0 precedence loop, resolved + // to iterate by substitution: when the exit alternative's + // scanned tokens were consumed exclusively by (a phantom or + // real) enclosing invocation of this same operator loop - no + // FOREIGN_CONSUME taint - every exit derivation of a sentence + // maps to an iterate derivation of the same sentence (the + // inner loop consumes the operators instead; all guards pass + // at class-0 entry precedences, so the mapped derivation is + // legal). Exit therefore never becomes uniquely viable, and + // whenever the adaptive engine terminates - unique iterate, + // or an exact ambiguity resolved to the minimum alternative - + // it answers iterate. Spurious (widening-born) exit + // viability only adds the conflict; the resolution matches + // the runtime either way. Iterate viability itself must be + // attested by a non-widened, non-foreign config so the + // accept is never based on an analysis artifact alone. + if (precRuleIndex >= 0 && precClassSubstitutable && exact + && conflicting.cardinality() == 2 + && conflicting.get(1) && conflicting.get(2)) { + boolean exitForeign = false; + boolean exitObligated = false; + boolean iterateReal = false; + for (ATNConfig c : cs) { + if (c.alt == 2) { + if ((c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) != 0) { + exitForeign = true; + } + // every phantom same-rule frame of the exit + // derivation must be obligation-free: the + // config's own position if it is in the rule, + // and every same-rule return state on its + // context chain (deeper phantom frames) + if (c.state.ruleIndex == precRuleIndex + && !precCompletableStates.get(c.state.stateNumber)) { + exitObligated = true; + } + if (hasObligatedReturn(c.context, + java.util.Collections.newSetFromMap( + new java.util.IdentityHashMap()))) { + exitObligated = true; + } + } + if (c.alt == 1 && (c.reachesIntoOuterContext + & (WIDENED_TAINT|FOREIGN_CONSUME_TAINT)) == 0) { + iterateReal = true; + } + } + if (!exitForeign && !exitObligated && iterateReal) { + res.exactAmbigConflicts.add(conflicting); + acceptAlts.set(d, 1); + continue; + } + } + // A conflict is trusted as an exact ambiguity only if it is - // exact, involves no over-approximated (hard-tainted) + // exact, involves no widened (analysis-only over-approximated) // configs, and its boundary usage is uniform: either the // conflict is internal to the decision's sub-language, or // every config popped through the decision boundary so the @@ -759,12 +945,17 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { // identically. Mixed usage (dangling-else shape) means // full-context prediction may kill the boundary-only // alternative, so min-alt is not behavior-preserving. - // Inside precedence classes exact conflicts are never - // trusted: the substitution argument has not been - // re-established under precedence filtering. - boolean untrusted = hardTainted || (anyBoundary && !allBoundary) + // Assumed-true precedence guards (PRECPRED_TAINT) do not + // block trust: the runtime's own SLL closure traverses + // non-frame-0 precedence predicates as epsilon under exactly + // the same assumption, so such configs mirror the runtime + // rather than over-approximate it. Inside precedence classes + // exact conflicts are otherwise never trusted: the min-alt + // substitution argument has not been re-established under + // precedence filtering (the enter/exit rule above is the + // one class-mode shape where it has). + boolean untrusted = widenedTainted || (anyBoundary && !allBoundary) || !trustExactAmbig; - BitSet conflicting = PredictionMode.getAlts(altSubsets); if (untrusted) res.approxConflicts.add(conflicting); else if (exact) res.exactAmbigConflicts.add(conflicting); else res.contextSensitiveConflicts.add(conflicting); @@ -777,6 +968,19 @@ else if (hybridMode) { // the conflict cannot be resolved statically: defer // this state to adaptivePredict acceptAlts.set(d, StaticDFA.ESCAPE); + if (System.getProperty("antlr.dfa.debug") != null) { + System.err.printf("ESCAPE-CONFLICT d=%d state=%d depth=%d exact=%s hard=%s anyB=%s allB=%s trustEA=%s alts=%s%n", + s.decision, d, stateDepth.get(d), exact, widenedTainted, + anyBoundary, allBoundary, trustExactAmbig, conflicting); + if ("full".equals(System.getProperty("antlr.dfa.debug"))) { + for (ATNConfig c : cs) { + System.err.printf(" alt=%d rule=%s state=%d taint=%d ctx=%s%n", + c.alt, g.getRule(c.state.ruleIndex).name, + c.state.stateNumber, c.reachesIntoOuterContext, + c.context); + } + } + } } else if (abortOnUntrustedConflict) { // not a trusted exact ambiguity: no widening level can @@ -789,10 +993,15 @@ else if (abortOnUntrustedConflict) { } if (hybridMode - && (stateDepth.get(d) >= hybridDepthCap || states.size() >= hybridStateCap)) { - // beyond the depth/size budget: don't expand, defer to + && (stateDepth.get(d) >= hybridDepthCap + || (states.size() >= hybridStateCap && stateDepth.get(d) >= 2))) { + // Beyond the depth/size budget: don't expand, defer to // adaptivePredict (BFS order makes this the deep, cold - // frontier - the shallow hot states are already built) + // frontier - the shallow hot states are already built). + // Depth 0 and 1 are exempt from the state budget: a wide + // first rank (bounded by the token alphabet) must not starve + // its own siblings, or single-token predictions - the + // dynamic majority - escape on sheer decision fanout. acceptAlts.set(d, StaticDFA.ESCAPE); continue; } @@ -1090,14 +1299,30 @@ else if (t instanceof WildcardTransition) { for (Map.Entry e : classLabels.entrySet()) { BitSet key = e.getKey(); Set succ = new LinkedHashSet(); - Set busy = new HashSet(); + Set busy = new HashSet(); for (int m = key.nextSetBit(0); m >= 0; m = key.nextSetBit(m+1)) { ATNConfig c = moveConfigs.get(m); if (moveIsStop.get(m)) { succ.add(c); } else { - closure(new ATNConfig(c, moveTargets.get(m)), succ, busy, res, 0); + ATNConfig advanced = new ATNConfig(c, moveTargets.get(m)); + if (precRuleIndex >= 0 + && (c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0 + && !isLoopConsumption(c)) { + // boundary-popped config consuming outside the + // operator loop: the phantom consumer is not an + // enclosing invocation of this loop + advanced.reachesIntoOuterContext |= FOREIGN_CONSUME_TAINT; + if ("full".equals(System.getProperty("antlr.dfa.debug")) + && (c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) == 0) { + System.err.printf("FOREIGN-MARK rule=%s state=%d alt=%d taint=%d ctx=%s label=%s%n", + g.getRule(c.state.ruleIndex).name, c.state.stateNumber, + c.alt, c.reachesIntoOuterContext, c.context, + labels.get(m).toString(g.getVocabulary())); + } + } + closure(advanced, succ, busy, res, 0); } } succ = canonical(succ); @@ -1134,8 +1359,22 @@ else if (t instanceof WildcardTransition) { * and a predicate reached that way belongs to a phantom frame, never to * frame 0.

*/ - protected void closure(ATNConfig config, Set configs, Set busy, Result res, int depth) { - if (!busy.add(config)) return; + protected void closure(ATNConfig config, Set configs, Set busy, Result res, int depth) { + // The busy key must distinguish pre- from post-boundary lineage + // (ATNConfig equality ignores taint): under per-precedence-class + // construction the decision rule's stop state is chased with the + // class's call-site filter from the decision's own frame + // (depth >= 0) but unfiltered from phantom enclosing frames + // (depth < 0). An identical (state, alt, ctx) key arriving first + // via the filtered pop must not swallow the later unfiltered one - + // that dedup once dropped the "exit two loops, BETWEEN takes the + // AND" derivations. The runtime has no such filter, so its + // first-arrival closure is always complete and its closureBusy + // key needs no lineage bit. + if (!busy.add(depth >= 0 ? (Object)config + : (Object)new java.util.AbstractMap.SimpleEntry(config, Boolean.TRUE))) { + return; + } ATNState p = config.state; if (p instanceof RuleStopState) { @@ -1242,6 +1481,27 @@ else if (t instanceof PredicateTransition) { closure(new ATNConfig(config, t.target), configs, busy, res, depth); } else if (t.isEpsilon()) { + if (boundaryChase && precRuleIndex >= 0 && p.ruleIndex == precRuleIndex + && depth >= 0) { + // Popping the decision boundary of the precedence rule + // under a per-class construction - from the decision's + // own frame (depth >= 0, first pop): only call sites + // whose precedence argument lies in the class interval + // can be the invocation this table serves (see + // precClassLo). FOLLOW links to incompatible call sites + // are phantom paths the runtime (with its real stack) + // never takes. Later same-rule stops (depth < 0) belong + // to phantom *enclosing* invocations of arbitrary entry + // precedence and must chase every call site: filtering + // them by this class's interval once dropped the real + // "exit two loops, let BETWEEN take the AND" derivations + // and misparsed FRAME BETWEEN a OR b AND c AND d. + RuleTransition call = callByFollowState().get(t.target.stateNumber); + if (call != null && call.target.ruleIndex == precRuleIndex + && (call.precedence < precClassLo || call.precedence > precClassHi)) { + continue; + } + } ATNConfig c2 = new ATNConfig(config, t.target); int newDepth = depth; if (boundaryChase) { @@ -1267,6 +1527,51 @@ else if (t.isEpsilon()) { } } + /** + * Is a token consumption by this (boundary-popped) config attributable + * to the operator loop of the precedence rule under construction - + * directly (at a loop-block state) or as an operand descent (a + * loop-block return state somewhere in the calling context)? + */ + protected boolean isLoopConsumption(ATNConfig c) { + if (precLoopStates.get(c.state.stateNumber)) return true; + return hasLoopReturn(c.context, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); + } + + /** + * Does the context chain contain a same-rule return state that is not + * epsilon-completable - a phantom frame of the precedence rule with an + * unmet obligation (see {@link #precCompletableStates})? + */ + private boolean hasObligatedReturn(PredictionContext ctx, Set visited) { + if (ctx == null || ctx.isEmpty() || !visited.add(ctx)) return false; + for (int i = 0; i < ctx.size(); i++) { + int rs = ctx.getReturnState(i); + if (rs != PredictionContext.EMPTY_RETURN_STATE) { + ATNState st = atn.states.get(rs); + if (st.ruleIndex == precRuleIndex + && !precCompletableStates.get(rs)) { + return true; + } + if (hasObligatedReturn(ctx.getParent(i), visited)) return true; + } + } + return false; + } + + private boolean hasLoopReturn(PredictionContext ctx, Set visited) { + if (ctx == null || ctx.isEmpty() || !visited.add(ctx)) return false; + for (int i = 0; i < ctx.size(); i++) { + int rs = ctx.getReturnState(i); + if (rs != PredictionContext.EMPTY_RETURN_STATE) { + if (precLoopStates.get(rs)) return true; + if (hasLoopReturn(ctx.getParent(i), visited)) return true; + } + } + return false; + } + /** Does a return state appear anywhere in a (possibly DAG-shaped) context? */ protected static boolean hasReturnState(PredictionContext ctx, int returnStateNumber) { return hasReturnState(ctx, returnStateNumber, From 6b8beeaa56e57409390c7b34b347721e09672f45 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 17 Jul 2026 01:58:48 -0400 Subject: [PATCH 08/48] BetweenExpr: minimal witness grammar for the BETWEEN...AND collision Isolates the production escape pattern in a small differential grammar (static + adaptive twins, pinned corners): BETWEEN as a suffix predicate on a pure-arithmetic value ladder, with a boolean AND/OR loop above - the dbt SQL shape. Findings recorded in the grammar and test comments: - Without value-position recursion into the boolean rule, the collision is an illusion: the BETWEEN separator AND is consumed by the predicate rule, the boolean loop's LA=AND is always iterate, and every decision is statically k=1 (verified with -Xdecision-report). Function calls, IN lists, subscripts and LIKE..ESCAPE suffixes do not change this. - The trigger is a value-position recursion back into the boolean rule: adding a lambda production (ID '->' b, Trino's identifier '->' expression primary) makes the collision genuinely context-sensitive. A BETWEEN bound can then end with a lambda whose body absorbs AND tokens: in `x BETWEEN y -> a AND b AND c` the first AND belongs to the lambda body and the second is the separator - which is which depends on the whole rest of the input. The boolean loop and the predicate decision become hybrid tables escaping exactly on these inputs (ANTLR_DFA_TRACE confirms escapes only on AND/OR at the loop and BETWEEN at the predicate decision). - Both engines resolve the ambiguous corners identically, maximal munch: `x BETWEEN y -> a AND b AND c` = BETWEEN(x, y -> (a AND b), c), while `x BETWEEN f -> a AND b` keeps the body minimal so the single AND can separate. Expected trees are pinned in test_semantics. This is also the explanation for the residual Trino escapes: they are not BETWEEN-specific, they are lambda-shaped (value-position boolean recursion), and their resolution must stay with the adaptive engine. Signed-off-by: Bo Lin --- runtime/Rust/gen_test_grammars.sh | 8 + runtime/Rust/grammars/BetweenExpr.g4 | 56 + .../Rust/tests/between_differential_tests.rs | 196 ++ .../gen/adaptive/betweenexprbaselistener.rs | 119 ++ .../tests/gen/adaptive/betweenexprlexer.rs | 149 ++ .../tests/gen/adaptive/betweenexprlistener.rs | 96 + .../tests/gen/adaptive/betweenexprparser.rs | 1689 ++++++++++++++++ .../Rust/tests/gen/betweenexprbaselistener.rs | 119 ++ runtime/Rust/tests/gen/betweenexprlexer.rs | 149 ++ runtime/Rust/tests/gen/betweenexprlistener.rs | 96 + runtime/Rust/tests/gen/betweenexprparser.rs | 1708 +++++++++++++++++ 11 files changed, 4385 insertions(+) create mode 100644 runtime/Rust/grammars/BetweenExpr.g4 create mode 100644 runtime/Rust/tests/between_differential_tests.rs create mode 100644 runtime/Rust/tests/gen/adaptive/betweenexprbaselistener.rs create mode 100644 runtime/Rust/tests/gen/adaptive/betweenexprlexer.rs create mode 100644 runtime/Rust/tests/gen/adaptive/betweenexprlistener.rs create mode 100644 runtime/Rust/tests/gen/adaptive/betweenexprparser.rs create mode 100644 runtime/Rust/tests/gen/betweenexprbaselistener.rs create mode 100644 runtime/Rust/tests/gen/betweenexprlexer.rs create mode 100644 runtime/Rust/tests/gen/betweenexprlistener.rs create mode 100644 runtime/Rust/tests/gen/betweenexprparser.rs diff --git a/runtime/Rust/gen_test_grammars.sh b/runtime/Rust/gen_test_grammars.sh index 2e5a63eaf7..b474f5e26b 100755 --- a/runtime/Rust/gen_test_grammars.sh +++ b/runtime/Rust/gen_test_grammars.sh @@ -16,6 +16,7 @@ declare -a GRAMMARS=( "StaticDFA" "LrDfa" "FuzzExpr" + "BetweenExpr" # "FHIRPath" ) @@ -30,6 +31,7 @@ declare -a ADDITIONAL_ARGS=( "-Xstatic-dfa" "-Xstatic-dfa" "-Xstatic-dfa" + "-Xstatic-dfa" ) for i in "${!GRAMMARS[@]}"; do @@ -52,3 +54,9 @@ done echo "Generating: FuzzExpr (adaptive twin)" (cd "$SCRIPT_DIR/grammars" && java -cp "$ANTLR_PATH" org.antlr.v4.Tool -Dlanguage=Rust \ -o ../tests/gen/adaptive FuzzExpr.g4) + +# Same differential twin for the BETWEEN-collision grammar +# (tests/between_differential_tests.rs). +echo "Generating: BetweenExpr (adaptive twin)" +(cd "$SCRIPT_DIR/grammars" && java -cp "$ANTLR_PATH" org.antlr.v4.Tool -Dlanguage=Rust \ + -o ../tests/gen/adaptive BetweenExpr.g4) diff --git a/runtime/Rust/grammars/BetweenExpr.g4 b/runtime/Rust/grammars/BetweenExpr.g4 new file mode 100644 index 0000000000..6457437bcf --- /dev/null +++ b/runtime/Rust/grammars/BetweenExpr.g4 @@ -0,0 +1,56 @@ +// Differential-test grammar isolating the BETWEEN ... AND ... collision +// with the boolean AND/OR loop, in the exact shape the dbt SQL grammars +// carry it (see tests/between_differential_tests.rs): +// +// booleanExpression : valueExpression predicate? | NOT b | b AND b | b OR b +// predicate : NOT? BETWEEN valueExpression AND valueExpression | ... +// +// BETWEEN is a *suffix* predicate on the pure-arithmetic value ladder, so +// its 'AND' separator collides with the boolean loop's 'AND' operator: +// after `a BETWEEN b AND c`, the boolean loop sees AND and must decide +// iterate (a new boolean operand) vs exit (the AND belongs to an enclosing +// construct). Statically provable shapes of this conflict resolve in the +// class tables of the b-loop decision; the rest escape to adaptivePredict. +// +// The grammar also carries 'NOT'? BETWEEN, whose lookahead collides with +// the prefix 'NOT' b alternative, and '(' b ')' in atoms, which puts +// boolean frames inside BETWEEN bounds (the phantom-FOLLOW mixing ground). +// +// The lambda production (ID '->' b) is what makes the collision genuinely +// context-sensitive - it puts a booleanExpression directly in a value +// position, so a BETWEEN bound can end with a lambda whose body absorbs +// 'AND' tokens: in `x BETWEEN y -> a AND b AND c` the first AND belongs +// to the lambda body and the second is the separator. Which AND is the +// separator depends on the whole rest of the input, so the b-loop and the +// predicate decision become hybrid tables that escape to adaptivePredict +// on exactly these inputs (verified: both engines parse the corners below +// identically, resolving maximal-munch like the runtime). DELETE the +// lambda production and every decision in this grammar is statically +// k=1 - function calls, IN lists, subscripts and LIKE..ESCAPE suffixes +// do NOT trigger the escape; only a value-position recursion back into +// the boolean rule does. This grammar is the minimal witness of the +// production (Trino) escape pattern, where lambdas play that role. +grammar BetweenExpr; + +s : b EOF ; + +b : v pred? # predicated + | 'NOT' b # not + | b 'AND' b # and + | b 'OR' b # or + ; + +pred : 'NOT'? 'BETWEEN' v 'AND' v # between + | ('='|'<'|'>') v # cmp + ; + +v : v ('*'|'/') v + | v ('+'|'-') v + | atom + ; + +atom : ID | INT | '(' b ')' | ID '->' b ; + +ID : [a-z]+ ; +INT : [0-9]+ ; +WS : [ \t\n]+ -> skip ; diff --git a/runtime/Rust/tests/between_differential_tests.rs b/runtime/Rust/tests/between_differential_tests.rs new file mode 100644 index 0000000000..9bb77c29de --- /dev/null +++ b/runtime/Rust/tests/between_differential_tests.rs @@ -0,0 +1,196 @@ +//! Differential corners for the BETWEEN ... AND ... collision with the +//! boolean AND/OR loop (grammar `grammars/BetweenExpr.g4`, generated twice: +//! `gen/betweenexprparser.rs` with `-Xstatic-dfa`, +//! `gen/adaptive/betweenexprparser.rs` without). +//! +//! The grammar mirrors the dbt SQL shape: BETWEEN is a suffix predicate on +//! the pure-arithmetic value ladder, so its `AND` separator is not the +//! boolean loop's `AND` - the two collide only through lookahead. The +//! lambda production (`ID '->' b`) recurses from a value position back +//! into the boolean rule, which is what makes the collision genuinely +//! context-sensitive: `x BETWEEN y -> a AND b AND c` parses the first AND +//! into the lambda body and takes the second as the separator, and which +//! AND is which depends on the whole rest of the input. On these shapes +//! the hybrid tables escape to adaptivePredict; both engines must agree +//! on every corner. (Without the lambda production every decision in this +//! grammar is statically k=1: the escape is triggered specifically by +//! value-position recursion into the boolean rule - not by function +//! calls, IN lists, subscripts, or LIKE..ESCAPE suffixes.) + +#[rustfmt::skip] +mod gen { + #![allow(non_snake_case)] + #![allow(clippy::all)] + pub mod betweenexprlexer; + pub mod betweenexprlistener; + pub mod betweenexprparser; + pub mod adaptive { + pub mod betweenexprlexer; + pub mod betweenexprlistener; + pub mod betweenexprparser; + } +} + +use dbt_antlr4::common_token_stream::CommonTokenStream; +use dbt_antlr4::recognizer::Recognizer; +use dbt_antlr4::token_factory::CommonTokenFactory; +use dbt_antlr4::trees::string_tree; +use dbt_antlr4::{Arena, InputStream}; + +fn parse_static(input: &str) -> Result { + Arena::with(|arena| { + let lexer = gen::betweenexprlexer::BetweenExprLexer::<_, CommonTokenFactory>::new( + arena, + InputStream::new(input), + ); + let tokens = CommonTokenStream::new(lexer); + let mut parser = gen::betweenexprparser::BetweenExprParser::new(arena, tokens); + parser + .s() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + .map_err(|e| format!("{e:?}")) + }) +} + +fn parse_adaptive(input: &str) -> Result { + Arena::with(|arena| { + let lexer = gen::adaptive::betweenexprlexer::BetweenExprLexer::<_, CommonTokenFactory>::new( + arena, + InputStream::new(input), + ); + let tokens = CommonTokenStream::new(lexer); + let mut parser = gen::adaptive::betweenexprparser::BetweenExprParser::new(arena, tokens); + parser + .s() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + .map_err(|e| format!("{e:?}")) + }) +} + +/// Corners of the BETWEEN/boolean-AND collision. Both engines must agree on +/// every one (tree or error). +const CORNERS: &[&str] = &[ + // plain BETWEEN + "a BETWEEN 1 AND 2", + "a BETWEEN 1 + 1 AND 2 * 3", + // BETWEEN then boolean AND: the upper bound must end at the first AND + "a BETWEEN 1 AND 2 AND b", + "a BETWEEN 1 AND 2 AND b AND c", + // boolean AND whose right operand is a BETWEEN + "a AND b BETWEEN 1 AND 2", + "a = 1 AND b BETWEEN 2 AND 3", + // BETWEEN on both sides of boolean operators + "a BETWEEN 1 AND 2 AND b BETWEEN 3 AND 4", + "a BETWEEN 1 AND 2 OR b BETWEEN 3 AND 4 AND c", + // long chains: the separator/operator choice repeats + "x BETWEEN a AND b AND c AND d AND e", + "a AND b BETWEEN 1 AND 2 AND c AND d BETWEEN 3 AND 4 AND e", + "a BETWEEN 1 + 2 AND 3 - 4 AND b BETWEEN 5 * 6 AND 7 / 8", + // NOT: prefix boolean NOT vs NOT BETWEEN + "NOT a BETWEEN 1 AND 2", + "a NOT BETWEEN 1 AND 2", + "a NOT BETWEEN 1 AND 2 AND b NOT BETWEEN 3 AND 4", + "NOT a AND b NOT BETWEEN 1 AND 2", + // comparison predicate + BETWEEN + "a = b AND c BETWEEN 1 AND 2", + "a < b OR c > d BETWEEN 1 AND 2", + // parentheses: boolean frames inside value bounds (phantom-FOLLOW + // mixing ground) and parenthesized predicates + "(a BETWEEN 1 AND 2) AND b", + "a BETWEEN (x AND y) AND z", + "a BETWEEN (x) AND (y)", + "a BETWEEN 1 AND (2) AND b", + "(a AND b) BETWEEN 1 AND 2", + "a BETWEEN (x AND y) AND (p OR q) AND r", + // lambdas: boolean bodies in value positions - the escape trigger. + // Which AND is the BETWEEN separator depends on the entire tail of + // the input (genuinely context-sensitive). + "x BETWEEN y -> a AND b AND c", + "x BETWEEN y -> a AND y -> b AND c", + "x BETWEEN a AND y -> b AND c", + "f -> a BETWEEN 1 AND 2", + "f -> a AND b", + "f -> a AND b BETWEEN 1 AND 2", + "x BETWEEN f -> a AND b", + "x BETWEEN f -> a AND b AND c", + "(x BETWEEN f -> a AND b) AND c", + "f -> g -> a AND b BETWEEN 1 AND 2 AND c", + // errors: both engines must fail identically + "a BETWEEN 1 AND", + "a BETWEEN", + "a AND", + "NOT BETWEEN 1 AND 2", + // a second BETWEEN after a completed predicate: not a value operator + "a BETWEEN 1 AND 2 BETWEEN 3 AND 4", + "a < b BETWEEN 1 AND 2", + // garbage + "a BETWEEN AND 2", + "1 AND", +]; + +#[test] +fn test_corners_differential() { + for input in CORNERS { + let s = parse_static(input); + let a = parse_adaptive(input); + assert_eq!( + a.is_ok(), + s.is_ok(), + "parse outcome diverges on {input:?}\nadaptive: {a:?}\nstatic: {s:?}" + ); + assert_eq!( + a, s, + "parse tree diverges on {input:?}\nadaptive: {a:?}\nstatic: {s:?}" + ); + } +} + +/// The meaning of the collision: the boolean `AND` after a BETWEEN always +/// binds the whole predicate, never the upper bound (the upper bound is a +/// value, and values cannot absorb `AND`). These expected trees lock the +/// semantics so a future table change cannot silently re-associate. +#[test] +fn test_semantics() { + // AND(BETWEEN(a, 1, 2), b) + assert_eq!( + parse_static("a BETWEEN 1 AND 2 AND b").unwrap(), + "(s (b (b (v (atom a)) (pred BETWEEN (v (atom 1)) AND (v (atom 2)))) AND (b (v (atom b)))) )" + ); + // AND(a, BETWEEN(b, 1, 2)) + assert_eq!( + parse_static("a AND b BETWEEN 1 AND 2").unwrap(), + "(s (b (b (v (atom a))) AND (b (v (atom b)) (pred BETWEEN (v (atom 1)) AND (v (atom 2))))) )" + ); + // NOT BETWEEN is a predicate suffix, not a prefix NOT + assert_eq!( + parse_static("a NOT BETWEEN 1 AND 2").unwrap(), + "(s (b (v (atom a)) (pred NOT BETWEEN (v (atom 1)) AND (v (atom 2)))) )" + ); + // OR(a, AND(BETWEEN(b,1,2), c)): AND binds tighter than OR + assert_eq!( + parse_static("a OR b BETWEEN 1 AND 2 AND c").unwrap(), + "(s (b (b (v (atom a))) OR (b (b (v (atom b)) (pred BETWEEN (v (atom 1)) AND (v (atom 2)))) AND (b (v (atom c))))) )" + ); + // parenthesized boolean inside a BETWEEN bound + assert_eq!( + parse_static("a BETWEEN (x AND y) AND z").unwrap(), + "(s (b (v (atom a)) (pred BETWEEN (v (atom ( (b (b (v (atom x))) AND (b (v (atom y)))) ))) AND (v (atom z)))) )" + ); + // lambda in a BETWEEN bound: maximal munch - the body absorbs the + // first AND, the second is the separator (both engines agree) + assert_eq!( + parse_static("x BETWEEN y -> a AND b AND c").unwrap(), + "(s (b (v (atom x)) (pred BETWEEN (v (atom y -> (b (b (v (atom a))) AND (b (v (atom b)))))) AND (v (atom c)))) )" + ); + // ...but when absorbing would strand the separator, the body stays + // minimal and the single AND separates + assert_eq!( + parse_static("x BETWEEN f -> a AND b").unwrap(), + "(s (b (v (atom x)) (pred BETWEEN (v (atom f -> (b (v (atom a))))) AND (v (atom b)))) )" + ); + // a lambda body can itself contain a BETWEEN + assert_eq!( + parse_static("f -> a BETWEEN 1 AND 2").unwrap(), + "(s (b (v (atom f -> (b (v (atom a)) (pred BETWEEN (v (atom 1)) AND (v (atom 2))))))) )" + ); +} diff --git a/runtime/Rust/tests/gen/adaptive/betweenexprbaselistener.rs b/runtime/Rust/tests/gen/adaptive/betweenexprbaselistener.rs new file mode 100644 index 0000000000..174db16c23 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/betweenexprbaselistener.rs @@ -0,0 +1,119 @@ +// Generated from BetweenExpr.g4 by ANTLR 4.13.2 + +use super::betweenexprparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by BetweenExprParser. + +pub trait BetweenExprBaseListener<'arena>: + ParseTreeListener<'arena, BetweenExprParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_not(&mut self, _ctx: &NotContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_not(&mut self, _ctx: &NotContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_predicated(&mut self, _ctx: &PredicatedContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_predicated(&mut self, _ctx: &PredicatedContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_or(&mut self, _ctx: &OrContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_or(&mut self, _ctx: &OrContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_and(&mut self, _ctx: &AndContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_and(&mut self, _ctx: &AndContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_between(&mut self, _ctx: &BetweenContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_between(&mut self, _ctx: &BetweenContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_cmp(&mut self, _ctx: &CmpContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_cmp(&mut self, _ctx: &CmpContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_v(&mut self, _ctx: &VContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_v(&mut self, _ctx: &VContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_atom(&mut self, _ctx: &AtomContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_atom(&mut self, _ctx: &AtomContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/adaptive/betweenexprlexer.rs b/runtime/Rust/tests/gen/adaptive/betweenexprlexer.rs new file mode 100644 index 0000000000..cd90e01b94 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/betweenexprlexer.rs @@ -0,0 +1,149 @@ +// Generated from BetweenExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const T__8:i32=9; +pub const T__9:i32=10; +pub const T__10:i32=11; +pub const T__11:i32=12; +pub const T__12:i32=13; +pub const T__13:i32=14; +pub const ID:i32=15; +pub const INT:i32=16; +pub const WS:i32=17; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;17] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "ID", "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;15] = [ + None, Some("'NOT'"), Some("'AND'"), Some("'OR'"), Some("'BETWEEN'"), Some("'='"), + Some("'<'"), Some("'>'"), Some("'*'"), Some("'/'"), Some("'+'"), Some("'-'"), + Some("'('"), Some("')'"), Some("'->'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;18] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, BetweenExprLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct BetweenExprLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { BetweenExprLexer } +dbt_antlr4::impl_deref! { lexer => BetweenExprLexer } + +impl<'input, 'arena, Input, TF> BetweenExprLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = BetweenExprLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct BetweenExprLexerActions { +} + +impl BetweenExprLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for BetweenExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for BetweenExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "BetweenExprLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 16] = [ + "CAAiuAEMAQQADgAEAg4CBAQOBAQGDgYECA4IBAoOCgQMDgwEDg4OBBAOEAQSDhIEFA4UBBYOFgQYDhgE", + "Gg4aBBwOHAQeDh4EIA4gAgACAAIAAgACAgICAgICAgIEAgQCBAIGAgYCBgIGAgYCBgIGAgYCCAIIAgoC", + "CgIMAgwCDgIOAhACEAISAhICFAIUAhYCFgIYAhgCGgIaAhoCHAgcmgEQHBYcGBycAQIeCB6kARAeFh4Y", + "HqYBAiAIIK4BECAWIBggsAECIAIgAAAiAgIGBAoGDggSChYMGg4eECISJhQqFi4YMho2HDoePiBCIgIA", + "BgIAwgH0AQIAYHIEABIUQEC8AQACAgAAAAAGAgAAAAAKAgAAAAAOAgAAAAASAgAAAAAWAgAAAAAaAgAA", + "AAAeAgAAAAAiAgAAAAAmAgAAAAAqAgAAAAAuAgAAAAAyAgAAAAA2AgAAAAA6AgAAAAA+AgAAAABCAgAA", + "AAJGAgAAAAZOAgAAAApWAgAAAA5cAgAAABJsAgAAABZwAgAAABp0AgAAAB54AgAAACJ8AgAAACaAAQIA", + "AAAqhAECAAAALogBAgAAADKMAQIAAAA2kAECAAAAOpgBAgAAAD6iAQIAAABCrAECAAAARkgKnAEAAEhK", + "Cp4BAABKTAqoAQAATAQCAAAATlAKggEAAFBSCpwBAABSVAqIAQAAVAgCAAAAVlgKngEAAFhaCqQBAABa", + "DAIAAABcXgqEAQAAXmAKigEAAGBiCqgBAABiZAquAQAAZGYKigEAAGZoCooBAABoagqcAQAAahACAAAA", + "bG4KegAAbhQCAAAAcHIKeAAAchgCAAAAdHYKfAAAdhwCAAAAeHoKVAAAeiACAAAAfH4KXgAAfiQCAAAA", + "gAGCAQpWAACCASgCAAAAhAGGAQpaAACGASwCAAAAiAGKAQpQAACKATACAAAAjAGOAQpSAACOATQCAAAA", + "kAGSAQpaAACSAZQBCnwAAJQBOAIAAACWAZoBDgAAAJgBlgECAAAAmgGcAQIAAACcAZgBAgAAAJwBngEC", + "AAAAngE8AgAAAKABpAEOAgAAogGgAQIAAACkAaYBAgAAAKYBogECAAAApgGoAQIAAACoAUACAAAAqgGu", + "AQ4EAACsAaoBAgAAAK4BsAECAAAAsAGsAQIAAACwAbIBAgAAALIBtAECAAAAtAG2AQwgAAC2AUQCAAAA", + "CACcAaYBsAECDAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/adaptive/betweenexprlistener.rs b/runtime/Rust/tests/gen/adaptive/betweenexprlistener.rs new file mode 100644 index 0000000000..7f98e47c19 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/betweenexprlistener.rs @@ -0,0 +1,96 @@ +#![allow(nonstandard_style)] +// Generated from BetweenExpr.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::betweenexprparser::*; + +pub trait BetweenExprListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, BetweenExprParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link BetweenExprParser#s}. + /// @param ctx the parse tree + fn enter_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link BetweenExprParser#s}. + /// @param ctx the parse tree + fn exit_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code not} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn enter_not<'input: 'arena>(&mut self, _ctx: &NotContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code not} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn exit_not<'input: 'arena>(&mut self, _ctx: &NotContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code predicated} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn enter_predicated<'input: 'arena>(&mut self, _ctx: &PredicatedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code predicated} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn exit_predicated<'input: 'arena>(&mut self, _ctx: &PredicatedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code or} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn enter_or<'input: 'arena>(&mut self, _ctx: &OrContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code or} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn exit_or<'input: 'arena>(&mut self, _ctx: &OrContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code and} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn enter_and<'input: 'arena>(&mut self, _ctx: &AndContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code and} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn exit_and<'input: 'arena>(&mut self, _ctx: &AndContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code between} + /// labeled alternative in {@link BetweenExprParser#pred}. + /// @param ctx the parse tree + fn enter_between<'input: 'arena>(&mut self, _ctx: &BetweenContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code between} + /// labeled alternative in {@link BetweenExprParser#pred}. + /// @param ctx the parse tree + fn exit_between<'input: 'arena>(&mut self, _ctx: &BetweenContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code cmp} + /// labeled alternative in {@link BetweenExprParser#pred}. + /// @param ctx the parse tree + fn enter_cmp<'input: 'arena>(&mut self, _ctx: &CmpContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code cmp} + /// labeled alternative in {@link BetweenExprParser#pred}. + /// @param ctx the parse tree + fn exit_cmp<'input: 'arena>(&mut self, _ctx: &CmpContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link BetweenExprParser#v}. + /// @param ctx the parse tree + fn enter_v<'input: 'arena>(&mut self, _ctx: &VContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link BetweenExprParser#v}. + /// @param ctx the parse tree + fn exit_v<'input: 'arena>(&mut self, _ctx: &VContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link BetweenExprParser#atom}. + /// @param ctx the parse tree + fn enter_atom<'input: 'arena>(&mut self, _ctx: &AtomContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link BetweenExprParser#atom}. + /// @param ctx the parse tree + fn exit_atom<'input: 'arena>(&mut self, _ctx: &AtomContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs b/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs new file mode 100644 index 0000000000..10c0b26f22 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs @@ -0,0 +1,1689 @@ +// Generated from BetweenExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::betweenexprlistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const BetweenExpr_T__0:i32=1; +pub const BetweenExpr_T__1:i32=2; +pub const BetweenExpr_T__2:i32=3; +pub const BetweenExpr_T__3:i32=4; +pub const BetweenExpr_T__4:i32=5; +pub const BetweenExpr_T__5:i32=6; +pub const BetweenExpr_T__6:i32=7; +pub const BetweenExpr_T__7:i32=8; +pub const BetweenExpr_T__8:i32=9; +pub const BetweenExpr_T__9:i32=10; +pub const BetweenExpr_T__10:i32=11; +pub const BetweenExpr_T__11:i32=12; +pub const BetweenExpr_T__12:i32=13; +pub const BetweenExpr_T__13:i32=14; +pub const BetweenExpr_ID:i32=15; +pub const BetweenExpr_INT:i32=16; +pub const BetweenExpr_WS:i32=17; +pub const BetweenExpr_EOF:i32=EOF; +pub const RULE_s:usize = 0; +pub const RULE_b:usize = 1; +pub const RULE_pred:usize = 2; +pub const RULE_v:usize = 3; +pub const RULE_atom:usize = 4; +pub const ruleNames: [&'static str; 5] = [ + "s", "b", "pred", "v", "atom" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;15] = [ + None, Some("'NOT'"), Some("'AND'"), Some("'OR'"), Some("'BETWEEN'"), Some("'='"), + Some("'<'"), Some("'>'"), Some("'*'"), Some("'/'"), Some("'+'"), Some("'-'"), + Some("'('"), Some("')'"), Some("'->'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;18] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, BetweenExprParserExt<'input, 'arena>, BetweenExprParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + BetweenExprParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: BetweenExprListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct BetweenExprTreeWalker; +impl BetweenExprTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: BetweenExprListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, BetweenExprParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum BetweenExprParserNodeKind { + SContext, + BContext, + PredContext, + VContext, + AtomContext, + Terminal, + Error, +} +pub type BetweenExprParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, BetweenExprParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => BetweenExprParser } +dbt_antlr4::impl_node_kind! { BetweenExprParserNodeKind { + BContext(BContextAll), PredContext(PredContextAll), ; SContext(enter_s, exit_s, ), VContext(enter_v, exit_v, ), AtomContext(enter_atom, exit_atom, ), + }; listener = dyn BetweenExprListener<'arena, Tok>, +} + +pub struct BetweenExprParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> BetweenExprParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for BetweenExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for BetweenExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "BetweenExpr.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena BetweenExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 1 => BetweenExprParser::<'input, 'arena, Input, TF>::b_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + 3 => BetweenExprParser::<'input, 'arena, Input, TF>::v_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn b_sempred(_ctx: Option<&'arena BContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 2) + } + 1 => { + recog.precpred(None, 1) + } + _ => true + } + } + + fn v_sempred(_ctx: Option<&'arena VContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 2 => { + recog.precpred(None, 3) + } + 3 => { + recog.precpred(None, 2) + } + _ => true + } + } +} +//------------------- s ---------------- +pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; + +pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::SContext } + fn get_rule_index(&self) -> usize { RULE_s } + fn make_node( + arena: &'arena Arena, + ctx: SContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { + ph: PhantomData + } + ) + } +} + +pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> SContextAttrs<'input, 'arena, Tok> for SContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == BetweenExpr_EOF) + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule b*/ + recog.base.set_state(10); + recog.b_rec(0)?; + recog.base.set_state(11); + recog.base.match_token(BetweenExpr_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- b ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum BContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + NotContext(NotContext<'input, 'arena, Tok>), + PredicatedContext(PredicatedContext<'input, 'arena, Tok>), + OrContext(OrContext<'input, 'arena, Tok>), + AndContext(AndContext<'input, 'arena, Tok>), + Error(BContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { BContextAll { } { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { BContextAll { } { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { BetweenExprParserNodeKind::BContextAll { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_node_inner! { BetweenExprParserNodeKind::BContext::BContextAll { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { BetweenExprListener::BetweenExprParserNodeKind::BContextAll { NotContext(enter_not, exit_not), PredicatedContext(enter_predicated, exit_predicated), OrContext(enter_or, exit_or), AndContext(enter_and, exit_and), } } + +impl<'input, 'arena, Tok> Deref for BContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn BContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use BContextAll::*; + match self{ + NotContext(inner) => inner, + PredicatedContext(inner) => inner, + OrContext(inner) => inner, + AndContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type BContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, BContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct BContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for BContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: BContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a BContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => BContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut BContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut BContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> BContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, BContextExt { + ph: PhantomData + } + ) + } +} + +pub trait BContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> BContextAttrs<'input, 'arena, Tok> for BContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type NotContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NotContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait NotContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> +{ + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct NotContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: BContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NotContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: NotContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::NotContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NotContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { + BContextAll::NotContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NotContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { + BContextAll::NotContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextExt<'input, 'arena, Tok> { + fn new(base: BContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut BContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + BContextAll::NotContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type PredicatedContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PredicatedContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait PredicatedContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn v(&self) -> Option<&'arena VContextAll<'input, 'arena, Tok>>; + fn pred(&self) -> Option<&'arena PredContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> +{ + fn v(&self) -> Option<&'arena VContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + fn pred(&self) -> Option<&'arena PredContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct PredicatedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: BContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PredicatedContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: PredicatedContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::PredicatedContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PredicatedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { + BContextAll::PredicatedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PredicatedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { + BContextAll::PredicatedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextExt<'input, 'arena, Tok> { + fn new(base: BContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut BContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + BContextAll::PredicatedContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type OrContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, OrContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait OrContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn b_all(&self) -> Vec<&'arena BContextAll<'input, 'arena, Tok>>; + fn b(&self, i: usize) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> +{ + fn b_all(&self) -> Vec<&'arena BContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn b(&self, i: usize) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct OrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: BContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for OrContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: OrContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::OrContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a OrContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { + BContextAll::OrContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut OrContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { + BContextAll::OrContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextExt<'input, 'arena, Tok> { + fn new(base: BContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut BContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + BContextAll::OrContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type AndContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AndContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait AndContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn b_all(&self) -> Vec<&'arena BContextAll<'input, 'arena, Tok>>; + fn b(&self, i: usize) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> +{ + fn b_all(&self) -> Vec<&'arena BContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn b(&self, i: usize) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AndContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: BContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AndContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: AndContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::AndContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AndContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { + BContextAll::AndContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AndContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { + BContextAll::AndContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextExt<'input, 'arena, Tok> { + fn new(base: BContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut BContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + BContextAll::AndContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn b(&mut self,) -> Result<&'arena BContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.b_rec(0) + } + + fn b_rec(&mut self, _p: i32) -> Result<&'arena BContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(BContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_b, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena BContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 2; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(20); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + BetweenExpr_T__11 |BetweenExpr_ID |BetweenExpr_INT => { + { + recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + /*InvokeRule v*/ + recog.base.set_state(14); + recog.v_rec(0)?; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(0,&mut recog.base)? { + x if x == 1=>{ + { + /*InvokeRule pred*/ + recog.base.set_state(15); + recog.pred()?; + } + } + + _ => {} + } + }} + BetweenExpr_T__0 => { + { + recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(18); + recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(19); + recog.b_rec(3)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(28); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AndContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(22); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(23); + recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(24); + recog.b_rec(3)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + OrContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(25); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(26); + recog.base.match_token(BetweenExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(27); + recog.b_rec(2)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- pred ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum PredContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + CmpContext(CmpContext<'input, 'arena, Tok>), + BetweenContext(BetweenContext<'input, 'arena, Tok>), + Error(PredContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { PredContextAll { } { CmpContext, BetweenContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { PredContextAll { } { CmpContext, BetweenContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { BetweenExprParserNodeKind::PredContextAll { CmpContext, BetweenContext, Error, } } +dbt_antlr4::impl_node_inner! { BetweenExprParserNodeKind::PredContext::PredContextAll { CmpContext, BetweenContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { BetweenExprListener::BetweenExprParserNodeKind::PredContextAll { CmpContext(enter_cmp, exit_cmp), BetweenContext(enter_between, exit_between), } } + +impl<'input, 'arena, Tok> Deref for PredContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn PredContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use PredContextAll::*; + match self{ + CmpContext(inner) => inner, + BetweenContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type PredContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PredContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct PredContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PredContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: PredContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PredContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PredContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PredContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PredContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, PredContextExt { + ph: PhantomData + } + ) + } +} + +pub trait PredContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> PredContextAttrs<'input, 'arena, Tok> for PredContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type CmpContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, CmpContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait CmpContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn v(&self) -> Option<&'arena VContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> +{ + fn v(&self) -> Option<&'arena VContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct CmpContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: PredContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CmpContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: CmpContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::CmpContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a CmpContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { + PredContextAll::CmpContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut CmpContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { + PredContextAll::CmpContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextExt<'input, 'arena, Tok> { + fn new(base: PredContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut PredContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + PredContextAll::CmpContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type BetweenContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, BetweenContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait BetweenContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn v_all(&self) -> Vec<&'arena VContextAll<'input, 'arena, Tok>>; + fn v(&self, i: usize) -> Option<&'arena VContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> BetweenContextAttrs<'input, 'arena, Tok> for BetweenContext<'input, 'arena, Tok> +{ + fn v_all(&self) -> Vec<&'arena VContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn v(&self, i: usize) -> Option<&'arena VContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct BetweenContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: PredContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for BetweenContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: BetweenContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::BetweenContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a BetweenContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { + PredContextAll::BetweenContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut BetweenContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { + PredContextAll::BetweenContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for BetweenContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> BetweenContextExt<'input, 'arena, Tok> { + fn new(base: PredContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut PredContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + PredContextAll::BetweenContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn pred(&mut self,) -> Result<&'arena PredContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_pred)?; + let _local_ctx_fn = |recog: &Self| -> &'arena PredContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + BetweenExpr_T__0 |BetweenExpr_T__3 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + BetweenContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena BetweenContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(34); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==BetweenExpr_T__0 { + { + recog.base.set_state(33); + recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; + } + } + + recog.base.set_state(36); + recog.base.match_token(BetweenExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule v*/ + recog.base.set_state(37); + recog.v_rec(0)?; + recog.base.set_state(38); + recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule v*/ + recog.base.set_state(39); + recog.v_rec(0)?; + }} + BetweenExpr_T__4 |BetweenExpr_T__5 |BetweenExpr_T__6 => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + CmpContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(41); + _la = recog.base.input.la(1); + if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 224) != 0)) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(42); + recog.v_rec(0)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- v ---------------- +pub type VContextAll<'input, 'arena, Tok = CommonToken<'input>> = VContext<'input, 'arena, Tok>; + +pub type VContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, VContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct VContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for VContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::VContext } + fn get_rule_index(&self) -> usize { RULE_v } + fn make_node( + arena: &'arena Arena, + ctx: VContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a VContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => VContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut VContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut VContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> VContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, VContextExt { + ph: PhantomData + } + ) + } +} + +pub trait VContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn atom(&self) -> Option<&'arena AtomContextAll<'input, 'arena, Tok>>; + fn v_all(&self) -> Vec<&'arena VContextAll<'input, 'arena, Tok>>; + fn v(&self, i: usize) -> Option<&'arena VContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> VContextAttrs<'input, 'arena, Tok> for VContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn atom(&self) -> Option<&'arena AtomContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + fn v_all(&self) -> Vec<&'arena VContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn v(&self, i: usize) -> Option<&'arena VContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn v(&mut self,) -> Result<&'arena VContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.v_rec(0) + } + + fn v_rec(&mut self, _p: i32) -> Result<&'arena VContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(VContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_v, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena VContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 6; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + { + /*InvokeRule atom*/ + recog.base.set_state(46); + recog.atom()?; + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(56); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(7,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(54); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(6,&mut recog.base)? { + 1 =>{ + { + /*recRuleAltStartAction*/ + let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; + + recog.base.set_state(48); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(49); + _la = recog.base.input.la(1); + if { !(_la==BetweenExpr_T__7 || _la==BetweenExpr_T__8) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(50); + recog.v_rec(4)?; + } + } + , + 2 =>{ + { + /*recRuleAltStartAction*/ + let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; + + recog.base.set_state(51); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(52); + _la = recog.base.input.la(1); + if { !(_la==BetweenExpr_T__9 || _la==BetweenExpr_T__10) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(53); + recog.v_rec(3)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(58); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(7,&mut recog.base)?; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- atom ---------------- +pub type AtomContextAll<'input, 'arena, Tok = CommonToken<'input>> = AtomContext<'input, 'arena, Tok>; + +pub type AtomContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AtomContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct AtomContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AtomContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::AtomContext } + fn get_rule_index(&self) -> usize { RULE_atom } + fn make_node( + arena: &'arena Arena, + ctx: AtomContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AtomContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AtomContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AtomContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AtomContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AtomContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, AtomContextExt { + ph: PhantomData + } + ) + } +} + +pub trait AtomContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> AtomContextAttrs<'input, 'arena, Tok> for AtomContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == BetweenExpr_ID) + } + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == BetweenExpr_INT) + } + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn atom(&mut self,) -> Result<&'arena AtomContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_atom)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AtomContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(68); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(8,&mut recog.base)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(59); + recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(60); + recog.base.match_token(BetweenExpr_INT,&mut recog.err_handler)?; + } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(61); + recog.base.match_token(BetweenExpr_T__11,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(62); + recog.b_rec(0)?; + recog.base.set_state(63); + recog.base.match_token(BetweenExpr_T__12,&mut recog.err_handler)?; + } + } + , + 4 =>{ + /*------- Outer Most Alt 4 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } + { + recog.base.set_state(65); + recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; + recog.base.set_state(66); + recog.base.match_token(BetweenExpr_T__13,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(67); + recog.b_rec(0)?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 12] = [ + "CAIijgEEAA4ABAIOAgQEDgQEBg4GBAgOCAIAAgACAAICAgICAgYCIhACAgICAgYCKhACAgICAgICAgIC", + "AgICCgI6EAIUAhgCQBICAgQGBEYQBAIEAgQCBAIEAgQCBAIEBgRYEAQCBgIGAgYCBgIGAgYCBgIGAgYK", + "Bm4QBhQGGAZ0EgYCCAIIAggCCAIIAggCCAIIAggGCIoBEAgCCAAEBAwKAAQIDBAABgIACg4CABASAgAU", + "FpgBABQCAAAABCgCAAAACFYCAAAADFoCAAAAEIgBAgAAABQWBgQCABYYCgAAAhgCAgAAABocDAIBABwg", + "BgwGAB4iBggEACAeAgAAACAiAgAAACIqAgAAACQmCgIAACYqBgQCBigaAgAAACgkAgAAACo8AgAAACwu", + "FAQAAC4wCgQAADA6BgQCBjI0FAIAADQ2CgYAADY6BgQCBDgsAgAAADgyAgAAADpAAgAAADw4AgAAADw+", + "AgAAAD4GAgAAAEA8AgAAAEJGCgIAAERCAgAAAERGAgAAAEZIAgAAAEhKCggAAEpMBgwGAExOCgQAAE5Q", + "BgwGAFBYAgAAAFJUDgAAAFRYBgwGAFZEAgAAAFZSAgAAAFgKAgAAAFpcDAYBAFxeBhAIAF5wAgAAAGBi", + "FAYAAGJkDgIAAGRuBgwGCGZoFAQAAGhqDgQAAGpuBgwGBmxgAgAAAGxmAgAAAG50AgAAAHBsAgAAAHBy", + "AgAAAHIOAgAAAHRwAgAAAHaKAQoeAAB4igEKIAAAenwKGAAAfH4GBAIAfoABChoAAIABigECAAAAggGE", + "AQoeAACEAYYBChwAAIYBigEGBAIAiAF2AgAAAIgBeAIAAACIAXoCAAAAiAGCAQIAAACKARICAAAAEiAo", + "ODxEVmxwiAE=" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/betweenexprbaselistener.rs b/runtime/Rust/tests/gen/betweenexprbaselistener.rs new file mode 100644 index 0000000000..174db16c23 --- /dev/null +++ b/runtime/Rust/tests/gen/betweenexprbaselistener.rs @@ -0,0 +1,119 @@ +// Generated from BetweenExpr.g4 by ANTLR 4.13.2 + +use super::betweenexprparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by BetweenExprParser. + +pub trait BetweenExprBaseListener<'arena>: + ParseTreeListener<'arena, BetweenExprParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_not(&mut self, _ctx: &NotContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_not(&mut self, _ctx: &NotContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_predicated(&mut self, _ctx: &PredicatedContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_predicated(&mut self, _ctx: &PredicatedContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_or(&mut self, _ctx: &OrContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_or(&mut self, _ctx: &OrContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_and(&mut self, _ctx: &AndContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_and(&mut self, _ctx: &AndContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_between(&mut self, _ctx: &BetweenContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_between(&mut self, _ctx: &BetweenContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_cmp(&mut self, _ctx: &CmpContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_cmp(&mut self, _ctx: &CmpContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_v(&mut self, _ctx: &VContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_v(&mut self, _ctx: &VContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_atom(&mut self, _ctx: &AtomContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link BetweenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_atom(&mut self, _ctx: &AtomContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/betweenexprlexer.rs b/runtime/Rust/tests/gen/betweenexprlexer.rs new file mode 100644 index 0000000000..cd90e01b94 --- /dev/null +++ b/runtime/Rust/tests/gen/betweenexprlexer.rs @@ -0,0 +1,149 @@ +// Generated from BetweenExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const T__8:i32=9; +pub const T__9:i32=10; +pub const T__10:i32=11; +pub const T__11:i32=12; +pub const T__12:i32=13; +pub const T__13:i32=14; +pub const ID:i32=15; +pub const INT:i32=16; +pub const WS:i32=17; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;17] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "ID", "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;15] = [ + None, Some("'NOT'"), Some("'AND'"), Some("'OR'"), Some("'BETWEEN'"), Some("'='"), + Some("'<'"), Some("'>'"), Some("'*'"), Some("'/'"), Some("'+'"), Some("'-'"), + Some("'('"), Some("')'"), Some("'->'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;18] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, BetweenExprLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct BetweenExprLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { BetweenExprLexer } +dbt_antlr4::impl_deref! { lexer => BetweenExprLexer } + +impl<'input, 'arena, Input, TF> BetweenExprLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = BetweenExprLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct BetweenExprLexerActions { +} + +impl BetweenExprLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for BetweenExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for BetweenExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "BetweenExprLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 16] = [ + "CAAiuAEMAQQADgAEAg4CBAQOBAQGDgYECA4IBAoOCgQMDgwEDg4OBBAOEAQSDhIEFA4UBBYOFgQYDhgE", + "Gg4aBBwOHAQeDh4EIA4gAgACAAIAAgACAgICAgICAgIEAgQCBAIGAgYCBgIGAgYCBgIGAgYCCAIIAgoC", + "CgIMAgwCDgIOAhACEAISAhICFAIUAhYCFgIYAhgCGgIaAhoCHAgcmgEQHBYcGBycAQIeCB6kARAeFh4Y", + "HqYBAiAIIK4BECAWIBggsAECIAIgAAAiAgIGBAoGDggSChYMGg4eECISJhQqFi4YMho2HDoePiBCIgIA", + "BgIAwgH0AQIAYHIEABIUQEC8AQACAgAAAAAGAgAAAAAKAgAAAAAOAgAAAAASAgAAAAAWAgAAAAAaAgAA", + "AAAeAgAAAAAiAgAAAAAmAgAAAAAqAgAAAAAuAgAAAAAyAgAAAAA2AgAAAAA6AgAAAAA+AgAAAABCAgAA", + "AAJGAgAAAAZOAgAAAApWAgAAAA5cAgAAABJsAgAAABZwAgAAABp0AgAAAB54AgAAACJ8AgAAACaAAQIA", + "AAAqhAECAAAALogBAgAAADKMAQIAAAA2kAECAAAAOpgBAgAAAD6iAQIAAABCrAECAAAARkgKnAEAAEhK", + "Cp4BAABKTAqoAQAATAQCAAAATlAKggEAAFBSCpwBAABSVAqIAQAAVAgCAAAAVlgKngEAAFhaCqQBAABa", + "DAIAAABcXgqEAQAAXmAKigEAAGBiCqgBAABiZAquAQAAZGYKigEAAGZoCooBAABoagqcAQAAahACAAAA", + "bG4KegAAbhQCAAAAcHIKeAAAchgCAAAAdHYKfAAAdhwCAAAAeHoKVAAAeiACAAAAfH4KXgAAfiQCAAAA", + "gAGCAQpWAACCASgCAAAAhAGGAQpaAACGASwCAAAAiAGKAQpQAACKATACAAAAjAGOAQpSAACOATQCAAAA", + "kAGSAQpaAACSAZQBCnwAAJQBOAIAAACWAZoBDgAAAJgBlgECAAAAmgGcAQIAAACcAZgBAgAAAJwBngEC", + "AAAAngE8AgAAAKABpAEOAgAAogGgAQIAAACkAaYBAgAAAKYBogECAAAApgGoAQIAAACoAUACAAAAqgGu", + "AQ4EAACsAaoBAgAAAK4BsAECAAAAsAGsAQIAAACwAbIBAgAAALIBtAECAAAAtAG2AQwgAAC2AUQCAAAA", + "CACcAaYBsAECDAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/betweenexprlistener.rs b/runtime/Rust/tests/gen/betweenexprlistener.rs new file mode 100644 index 0000000000..7f98e47c19 --- /dev/null +++ b/runtime/Rust/tests/gen/betweenexprlistener.rs @@ -0,0 +1,96 @@ +#![allow(nonstandard_style)] +// Generated from BetweenExpr.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::betweenexprparser::*; + +pub trait BetweenExprListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, BetweenExprParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link BetweenExprParser#s}. + /// @param ctx the parse tree + fn enter_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link BetweenExprParser#s}. + /// @param ctx the parse tree + fn exit_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code not} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn enter_not<'input: 'arena>(&mut self, _ctx: &NotContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code not} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn exit_not<'input: 'arena>(&mut self, _ctx: &NotContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code predicated} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn enter_predicated<'input: 'arena>(&mut self, _ctx: &PredicatedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code predicated} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn exit_predicated<'input: 'arena>(&mut self, _ctx: &PredicatedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code or} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn enter_or<'input: 'arena>(&mut self, _ctx: &OrContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code or} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn exit_or<'input: 'arena>(&mut self, _ctx: &OrContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code and} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn enter_and<'input: 'arena>(&mut self, _ctx: &AndContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code and} + /// labeled alternative in {@link BetweenExprParser#b}. + /// @param ctx the parse tree + fn exit_and<'input: 'arena>(&mut self, _ctx: &AndContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code between} + /// labeled alternative in {@link BetweenExprParser#pred}. + /// @param ctx the parse tree + fn enter_between<'input: 'arena>(&mut self, _ctx: &BetweenContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code between} + /// labeled alternative in {@link BetweenExprParser#pred}. + /// @param ctx the parse tree + fn exit_between<'input: 'arena>(&mut self, _ctx: &BetweenContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code cmp} + /// labeled alternative in {@link BetweenExprParser#pred}. + /// @param ctx the parse tree + fn enter_cmp<'input: 'arena>(&mut self, _ctx: &CmpContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code cmp} + /// labeled alternative in {@link BetweenExprParser#pred}. + /// @param ctx the parse tree + fn exit_cmp<'input: 'arena>(&mut self, _ctx: &CmpContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link BetweenExprParser#v}. + /// @param ctx the parse tree + fn enter_v<'input: 'arena>(&mut self, _ctx: &VContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link BetweenExprParser#v}. + /// @param ctx the parse tree + fn exit_v<'input: 'arena>(&mut self, _ctx: &VContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link BetweenExprParser#atom}. + /// @param ctx the parse tree + fn enter_atom<'input: 'arena>(&mut self, _ctx: &AtomContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link BetweenExprParser#atom}. + /// @param ctx the parse tree + fn exit_atom<'input: 'arena>(&mut self, _ctx: &AtomContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs new file mode 100644 index 0000000000..cefbf8d4b7 --- /dev/null +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -0,0 +1,1708 @@ +// Generated from BetweenExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::betweenexprlistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const BetweenExpr_T__0:i32=1; +pub const BetweenExpr_T__1:i32=2; +pub const BetweenExpr_T__2:i32=3; +pub const BetweenExpr_T__3:i32=4; +pub const BetweenExpr_T__4:i32=5; +pub const BetweenExpr_T__5:i32=6; +pub const BetweenExpr_T__6:i32=7; +pub const BetweenExpr_T__7:i32=8; +pub const BetweenExpr_T__8:i32=9; +pub const BetweenExpr_T__9:i32=10; +pub const BetweenExpr_T__10:i32=11; +pub const BetweenExpr_T__11:i32=12; +pub const BetweenExpr_T__12:i32=13; +pub const BetweenExpr_T__13:i32=14; +pub const BetweenExpr_ID:i32=15; +pub const BetweenExpr_INT:i32=16; +pub const BetweenExpr_WS:i32=17; +pub const BetweenExpr_EOF:i32=EOF; +pub const RULE_s:usize = 0; +pub const RULE_b:usize = 1; +pub const RULE_pred:usize = 2; +pub const RULE_v:usize = 3; +pub const RULE_atom:usize = 4; +pub const ruleNames: [&'static str; 5] = [ + "s", "b", "pred", "v", "atom" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;15] = [ + None, Some("'NOT'"), Some("'AND'"), Some("'OR'"), Some("'BETWEEN'"), Some("'='"), + Some("'<'"), Some("'>'"), Some("'*'"), Some("'/'"), Some("'+'"), Some("'-'"), + Some("'('"), Some("')'"), Some("'->'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;18] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + None, None, None, Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, BetweenExprParserExt<'input, 'arena>, BetweenExprParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + BetweenExprParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: BetweenExprListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct BetweenExprTreeWalker; +impl BetweenExprTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: BetweenExprListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, BetweenExprParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum BetweenExprParserNodeKind { + SContext, + BContext, + PredContext, + VContext, + AtomContext, + Terminal, + Error, +} +pub type BetweenExprParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, BetweenExprParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => BetweenExprParser } +dbt_antlr4::impl_node_kind! { BetweenExprParserNodeKind { + BContext(BContextAll), PredContext(PredContextAll), ; SContext(enter_s, exit_s, ), VContext(enter_v, exit_v, ), AtomContext(enter_atom, exit_atom, ), + }; listener = dyn BetweenExprListener<'arena, Tok>, +} + +pub struct BetweenExprParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> BetweenExprParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for BetweenExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for BetweenExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "BetweenExpr.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena BetweenExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 1 => BetweenExprParser::<'input, 'arena, Input, TF>::b_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + 3 => BetweenExprParser::<'input, 'arena, Input, TF>::v_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn b_sempred(_ctx: Option<&'arena BContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 2) + } + 1 => { + recog.precpred(None, 1) + } + _ => true + } + } + + fn v_sempred(_ctx: Option<&'arena VContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 2 => { + recog.precpred(None, 3) + } + 3 => { + recog.precpred(None, 2) + } + _ => true + } + } +} +//------------------- s ---------------- +pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; + +pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::SContext } + fn get_rule_index(&self) -> usize { RULE_s } + fn make_node( + arena: &'arena Arena, + ctx: SContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { + ph: PhantomData + } + ) + } +} + +pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> SContextAttrs<'input, 'arena, Tok> for SContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == BetweenExpr_EOF) + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule b*/ + recog.base.set_state(10); + recog.b_rec(0)?; + recog.base.set_state(11); + recog.base.match_token(BetweenExpr_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- b ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum BContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + NotContext(NotContext<'input, 'arena, Tok>), + PredicatedContext(PredicatedContext<'input, 'arena, Tok>), + OrContext(OrContext<'input, 'arena, Tok>), + AndContext(AndContext<'input, 'arena, Tok>), + Error(BContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { BContextAll { } { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { BContextAll { } { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { BetweenExprParserNodeKind::BContextAll { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_node_inner! { BetweenExprParserNodeKind::BContext::BContextAll { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { BetweenExprListener::BetweenExprParserNodeKind::BContextAll { NotContext(enter_not, exit_not), PredicatedContext(enter_predicated, exit_predicated), OrContext(enter_or, exit_or), AndContext(enter_and, exit_and), } } + +impl<'input, 'arena, Tok> Deref for BContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn BContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use BContextAll::*; + match self{ + NotContext(inner) => inner, + PredicatedContext(inner) => inner, + OrContext(inner) => inner, + AndContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type BContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, BContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct BContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for BContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: BContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a BContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => BContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut BContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut BContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> BContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, BContextExt { + ph: PhantomData + } + ) + } +} + +pub trait BContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> BContextAttrs<'input, 'arena, Tok> for BContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type NotContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NotContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait NotContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> +{ + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct NotContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: BContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NotContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: NotContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::NotContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NotContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { + BContextAll::NotContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NotContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { + BContextAll::NotContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextExt<'input, 'arena, Tok> { + fn new(base: BContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut BContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + BContextAll::NotContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type PredicatedContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PredicatedContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait PredicatedContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn v(&self) -> Option<&'arena VContextAll<'input, 'arena, Tok>>; + fn pred(&self) -> Option<&'arena PredContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> +{ + fn v(&self) -> Option<&'arena VContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + fn pred(&self) -> Option<&'arena PredContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct PredicatedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: BContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PredicatedContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: PredicatedContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::PredicatedContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PredicatedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { + BContextAll::PredicatedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PredicatedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { + BContextAll::PredicatedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextExt<'input, 'arena, Tok> { + fn new(base: BContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut BContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + BContextAll::PredicatedContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type OrContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, OrContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait OrContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn b_all(&self) -> Vec<&'arena BContextAll<'input, 'arena, Tok>>; + fn b(&self, i: usize) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> +{ + fn b_all(&self) -> Vec<&'arena BContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn b(&self, i: usize) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct OrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: BContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for OrContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: OrContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::OrContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a OrContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { + BContextAll::OrContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut OrContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { + BContextAll::OrContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextExt<'input, 'arena, Tok> { + fn new(base: BContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut BContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + BContextAll::OrContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type AndContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AndContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait AndContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn b_all(&self) -> Vec<&'arena BContextAll<'input, 'arena, Tok>>; + fn b(&self, i: usize) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> +{ + fn b_all(&self) -> Vec<&'arena BContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn b(&self, i: usize) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AndContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: BContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AndContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } + fn get_rule_index(&self) -> usize { RULE_b } + fn make_node( + arena: &'arena Arena, + ctx: AndContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(BContextAll::AndContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AndContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { + BContextAll::AndContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AndContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { + BContextAll::AndContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextExt<'input, 'arena, Tok> { + fn new(base: BContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut BContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + BContextAll::AndContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn b(&mut self,) -> Result<&'arena BContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.b_rec(0) + } + + fn b_rec(&mut self, _p: i32) -> Result<&'arena BContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(BContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_b, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena BContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 2; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(20); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + BetweenExpr_T__11 |BetweenExpr_ID |BetweenExpr_INT => { + { + recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + /*InvokeRule v*/ + recog.base.set_state(14); + recog.v_rec(0)?; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(0)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(0,&mut recog.base)? } else { _sdp } } { + x if x == 1 =>{ + { + /*InvokeRule pred*/ + recog.base.set_state(15); + recog.pred()?; + } + } + + _ => {} + } + }} + BetweenExpr_T__0 => { + { + recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(18); + recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(19); + recog.b_rec(3)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(28); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } } { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AndContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(22); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(23); + recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(24); + recog.b_rec(3)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + OrContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(25); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(26); + recog.base.match_token(BetweenExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(27); + recog.b_rec(2)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- pred ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum PredContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + CmpContext(CmpContext<'input, 'arena, Tok>), + BetweenContext(BetweenContext<'input, 'arena, Tok>), + Error(PredContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { PredContextAll { } { CmpContext, BetweenContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { PredContextAll { } { CmpContext, BetweenContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { BetweenExprParserNodeKind::PredContextAll { CmpContext, BetweenContext, Error, } } +dbt_antlr4::impl_node_inner! { BetweenExprParserNodeKind::PredContext::PredContextAll { CmpContext, BetweenContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { BetweenExprListener::BetweenExprParserNodeKind::PredContextAll { CmpContext(enter_cmp, exit_cmp), BetweenContext(enter_between, exit_between), } } + +impl<'input, 'arena, Tok> Deref for PredContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn PredContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use PredContextAll::*; + match self{ + CmpContext(inner) => inner, + BetweenContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type PredContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PredContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct PredContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PredContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: PredContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PredContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PredContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PredContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PredContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, PredContextExt { + ph: PhantomData + } + ) + } +} + +pub trait PredContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> PredContextAttrs<'input, 'arena, Tok> for PredContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type CmpContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, CmpContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait CmpContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn v(&self) -> Option<&'arena VContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> +{ + fn v(&self) -> Option<&'arena VContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct CmpContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: PredContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CmpContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: CmpContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::CmpContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a CmpContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { + PredContextAll::CmpContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut CmpContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { + PredContextAll::CmpContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextExt<'input, 'arena, Tok> { + fn new(base: PredContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut PredContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + PredContextAll::CmpContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type BetweenContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, BetweenContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; + +pub trait BetweenContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn v_all(&self) -> Vec<&'arena VContextAll<'input, 'arena, Tok>>; + fn v(&self, i: usize) -> Option<&'arena VContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> BetweenContextAttrs<'input, 'arena, Tok> for BetweenContext<'input, 'arena, Tok> +{ + fn v_all(&self) -> Vec<&'arena VContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn v(&self, i: usize) -> Option<&'arena VContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct BetweenContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: PredContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for BetweenContextExt<'input, 'arena, Tok> +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: BetweenContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::BetweenContext(ctx)) + } + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a BetweenContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { + PredContextAll::BetweenContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut BetweenContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { + PredContextAll::BetweenContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for BetweenContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> BetweenContextExt<'input, 'arena, Tok> { + fn new(base: PredContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut BetweenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut PredContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + PredContextAll::BetweenContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn pred(&mut self,) -> Result<&'arena PredContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_pred)?; + let _local_ctx_fn = |recog: &Self| -> &'arena PredContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + BetweenExpr_T__0 |BetweenExpr_T__3 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + BetweenContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena BetweenContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(34); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==BetweenExpr_T__0 { + { + recog.base.set_state(33); + recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; + } + } + + recog.base.set_state(36); + recog.base.match_token(BetweenExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule v*/ + recog.base.set_state(37); + recog.v_rec(0)?; + recog.base.set_state(38); + recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule v*/ + recog.base.set_state(39); + recog.v_rec(0)?; + }} + BetweenExpr_T__4 |BetweenExpr_T__5 |BetweenExpr_T__6 => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + CmpContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(41); + _la = recog.base.input.la(1); + if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 224) != 0)) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(42); + recog.v_rec(0)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- v ---------------- +pub type VContextAll<'input, 'arena, Tok = CommonToken<'input>> = VContext<'input, 'arena, Tok>; + +pub type VContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, VContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct VContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for VContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::VContext } + fn get_rule_index(&self) -> usize { RULE_v } + fn make_node( + arena: &'arena Arena, + ctx: VContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a VContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => VContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut VContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut VContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> VContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, VContextExt { + ph: PhantomData + } + ) + } +} + +pub trait VContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn atom(&self) -> Option<&'arena AtomContextAll<'input, 'arena, Tok>>; + fn v_all(&self) -> Vec<&'arena VContextAll<'input, 'arena, Tok>>; + fn v(&self, i: usize) -> Option<&'arena VContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> VContextAttrs<'input, 'arena, Tok> for VContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn atom(&self) -> Option<&'arena AtomContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + fn v_all(&self) -> Vec<&'arena VContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn v(&self, i: usize) -> Option<&'arena VContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn v(&mut self,) -> Result<&'arena VContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.v_rec(0) + } + + fn v_rec(&mut self, _p: i32) -> Result<&'arena VContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(VContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_v, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena VContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 6; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + { + /*InvokeRule atom*/ + recog.base.set_state(46); + recog.atom()?; + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(56); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(7)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(7,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(54); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } } { + 1 =>{ + { + /*recRuleAltStartAction*/ + let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; + + recog.base.set_state(48); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(49); + _la = recog.base.input.la(1); + if { !(_la==BetweenExpr_T__7 || _la==BetweenExpr_T__8) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(50); + recog.v_rec(4)?; + } + } + , + 2 =>{ + { + /*recRuleAltStartAction*/ + let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; + + recog.base.set_state(51); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(52); + _la = recog.base.input.la(1); + if { !(_la==BetweenExpr_T__9 || _la==BetweenExpr_T__10) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(53); + recog.v_rec(3)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(58); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(7)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(7,&mut recog.base)? } else { _sdp } }; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- atom ---------------- +pub type AtomContextAll<'input, 'arena, Tok = CommonToken<'input>> = AtomContext<'input, 'arena, Tok>; + +pub type AtomContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AtomContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct AtomContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AtomContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = BetweenExprParserNodeKind; + fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::AtomContext } + fn get_rule_index(&self) -> usize { RULE_atom } + fn make_node( + arena: &'arena Arena, + ctx: AtomContext<'input, 'arena, Tok>, + ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AtomContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AtomContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AtomContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AtomContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AtomContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, AtomContextExt { + ph: PhantomData + } + ) + } +} + +pub trait AtomContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> AtomContextAttrs<'input, 'arena, Tok> for AtomContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == BetweenExpr_ID) + } + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == BetweenExpr_INT) + } + fn b(&self) -> Option<&'arena BContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} + +impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn atom(&mut self,) -> Result<&'arena AtomContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_atom)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AtomContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(68); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(8)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(8,&mut recog.base)? } else { _sdp } } { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(59); + recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; + } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(60); + recog.base.match_token(BetweenExpr_INT,&mut recog.err_handler)?; + } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(61); + recog.base.match_token(BetweenExpr_T__11,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(62); + recog.b_rec(0)?; + recog.base.set_state(63); + recog.base.match_token(BetweenExpr_T__12,&mut recog.err_handler)?; + } + } + , + 4 =>{ + /*------- Outer Most Alt 4 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } + { + recog.base.set_state(65); + recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; + recog.base.set_state(66); + recog.base.match_token(BetweenExpr_T__13,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(67); + recog.b_rec(0)?; + } + } + + _ => {} + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +// the serialized ATN is followed by 9 static SLL prediction tables (-Xstatic-dfa): +// decision 3: precedence-dispatched over cutoffs [1, 2], tables [4 5 6] +// decision 7: precedence-dispatched over cutoffs [2, 3], tables [7 8 6] +// decision 0: LL(k), k=1, 9 states, 3 adaptive escapes +// decision 2: LL(k), k=1, 3 states +// decision 6: LL(k), k=1, 3 states +// decision 8: LL(k), k=2, 13 states +// table 4 (decision 3): LL(k), k=1, 9 states, 2 adaptive escapes +// table 5 (decision 3): LL(k), k=1, 9 states, 1 adaptive escapes +// table 6 (decision 3): LL(k), k=0, 1 states +// table 7 (decision 7): LL(k), k=1, 9 states +// table 8 (decision 7): LL(k), k=1, 10 states, 1 adaptive escapes +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 19] = [ + "CAIijgEEAA4ABAIOAgQEDgQEBg4GBAgOCAIAAgACAAICAgICAgYCIhACAgICAgYCKhACAgICAgICAgIC", + "AgICCgI6EAIUAhgCQBICAgQGBEYQBAIEAgQCBAIEAgQCBAIEBgRYEAQCBgIGAgYCBgIGAgYCBgIGAgYK", + "Bm4QBhQGGAZ0EgYCCAIIAggCCAIIAggCCAIIAggGCIoBEAgCCAAEBAwKAAQIDBAABgIACg4CABASAgAU", + "FpgBABQCAAAABCgCAAAACFYCAAAADFoCAAAAEIgBAgAAABQWBgQCABYYCgAAAhgCAgAAABocDAIBABwg", + "BgwGAB4iBggEACAeAgAAACAiAgAAACIqAgAAACQmCgIAACYqBgQCBigaAgAAACgkAgAAACo8AgAAACwu", + "FAQAAC4wCgQAADA6BgQCBjI0FAIAADQ2CgYAADY6BgQCBDgsAgAAADgyAgAAADpAAgAAADw4AgAAADw+", + "AgAAAD4GAgAAAEA8AgAAAEJGCgIAAERCAgAAAERGAgAAAEZIAgAAAEhKCggAAEpMBgwGAExOCgQAAE5Q", + "BgwGAFBYAgAAAFJUDgAAAFRYBgwGAFZEAgAAAFZSAgAAAFgKAgAAAFpcDAYBAFxeBhAIAF5wAgAAAGBi", + "FAYAAGJkDgIAAGRuBgwGCGZoFAQAAGhqDgQAAGpuBgwGBmxgAgAAAGxmAgAAAG50AgAAAHBsAgAAAHBy", + "AgAAAHIOAgAAAHRwAgAAAHaKAQoeAAB4igEKIAAAenwKGAAAfH4GBAIAfoABChoAAIABigECAAAAggGE", + "AQoeAACEAYYBChwAAIYBigEGBAIAiAF2AgAAAIgBeAIAAACIAXoCAAAAiAGCAQIAAACKARICAAAAEiAo", + "ODxEVmxwiAEKEhIAEjAABAEEBAEBBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", + "EBYOGhoQBAYMAAIEAAAAAAwMDAQEAgYGBAwGDAACBAAAAAAMDAwQEgIUFgQQGkgABgAEAgICAgICAgII", + "AAACAAAAAAAAAAAAAAASEkhISEhISEhISEhIGBgCHh4EICAGAQEIAgIKBAQMBgYOCAgQCg4SEBYUGhoW", + "HBwYARIwAAQEAQEEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAES", + "MAAEBAEEBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4aGhABAgAEAAAA", + "ARIwAAQEBAQEBAIEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAEUNgAE", + "BAQEBAQBBAQEAAAAAAAAAAAAADY2NjY2NjY2NjYBAQICAgQEBAYGBggICAoKDgwQEg4UFhAaGhIEBgQC", + "BAgKDA4EBAYOEAw=" +]; \ No newline at end of file From 3f6e4b2137053f3d2251d6c3c6038e3a7ade2a70 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 17 Jul 2026 07:47:46 -0400 Subject: [PATCH 09/48] Java runtime: antlr.dfa.trace escape tracing in dfaPredict Mirror of the Rust runtime's ANTLR_DFA_TRACE: with -Dantlr.dfa.trace, every prediction the static tables defer to the adaptive engine is logged (decision, precedence, table state) - the tool for finding which decisions a given input keeps escaping on. Signed-off-by: Bo Lin --- runtime/Java/src/org/antlr/v4/runtime/Parser.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java index f7fb8e7ae8..c17e45f871 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java @@ -570,6 +570,9 @@ public int dfaPredict(StaticDFATables tables, int decision) // hybrid-table escape: rerun the prediction through the // adaptive engine (no input was consumed, so the rescan // starts clean) + if ( System.getProperty("antlr.dfa.trace") != null ) { + System.err.println("DFA-TRACE escape d="+decision+" prec="+getPrecedence()+" state="+s+" la1="+_input.LA(1)); + } return getInterpreter().adaptivePredict(_input, decision, _ctx); } int next = tables.edge(table, s, _input.LA(i)); From f7e2bf4ef80826c3dddc7ef764eaf06255a1d1ed Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 17 Jul 2026 11:46:29 -0400 Subject: [PATCH 10/48] Adjacency-aware loop block and pending-token obligations: simple arithmetic resolves in-table (Trino 1+1: 0 escapes, 2.7x) The class-0 operator-loop escape behind "SELECT 1 + 1" falling back to adaptivePredict has been eliminated through three analysis refinements, each validated against the differential oracles: 1. The loop block is now rooted at the rule start, covering the base-operand descent. Previously the BFS started at the loop's iterate branch, so the follow state of the base operand's rule reference was outside the block and consumption inside a nested invocation's operand was misclassified FOREIGN, vetoing the enter/exit substitution on every plain binary-operator conflict. 2. Obligation checking uses pending-token states: positions that can reach a token match by epsilon without passing through the loop decision (reverse-epsilon closure of token positions, blocked at the decision). A phantom frame owing such a token - Send's list element returning into a pending ','/'>>' - has no iterate-side counterpart and keeps the veto; a frame blocked only by the decision owes exactly the next operator, which the iterate reading owes too. The own-state veto fires only when the operand's invocation returns into pending tokens (compound alternatives); the operand of a simple binary/unary operator returns to the alternative tail and is shared with iterate. 3. The enter/exit substitution now requires every guarded alternative of the loop rule to be simple: at most one rule invocation and no internal iteration. This was forced by a demonstrated unsoundness: for expr (',' expr)* '>>' expr the iterate reading of "a,c>>x" completes the inner Send as a list element and dies (the outer Send's '>>' is missing) while the exit reading completes the sentence - accepting iterate there produced the nested tree (expr a) , ((expr c) >> (expr x)) instead of the flat (expr a) , (expr c) >> (expr x). Compound loops keep escaping to the adaptive engine. An additional mechanism was built and deliberately removed during development: pruning boundary-popped re-invocations of the precedence rule from outside the loop block. It was unsound - the BetweenExpr differential (a < b OR c > d BETWEEN 1 AND 2) caught it accepting a second predicate - and turned out unnecessary: refinements 1-3 suffice. The diagnostics that guided the work stay (property-gated): -Dantlr.dfa.debug=states/veto decision dumps with rule-decoded contexts. Results (Trino, Rust, 30k parses each): - SELECT 1 + 1 FROM MY_TABLE: 5.6us -> 2.1us (2.7x), zero escapes - SELECT T1.C1, ..., T4.C4 FROM MY_TABLE: 17.3us -> 3.6us (4.8x) - valueExpression class 0 now 100% table coverage; all six SQL grammars keep all LR loops static with zero bare adaptive sites Verified: cargo 55/55 (fuzz + BetweenExpr + lr_dfa differentials), runtime suites 707/707 (incl. ReturnValueAndActionsList), tool -testsuite 694, B4 17/17 escape corners, Send 9/9, p1probe 24/24, lrdfa 8/8. Signed-off-by: Bo Lin --- runtime/Rust/tests/gen/betweenexprparser.rs | 4 +- .../antlr/v4/analysis/DecisionClassifier.java | 345 ++++++++++++++---- 2 files changed, 284 insertions(+), 65 deletions(-) diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index cefbf8d4b7..734bec3ff0 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -1677,7 +1677,7 @@ where // decision 2: LL(k), k=1, 3 states // decision 6: LL(k), k=1, 3 states // decision 8: LL(k), k=2, 13 states -// table 4 (decision 3): LL(k), k=1, 9 states, 2 adaptive escapes +// table 4 (decision 3): LL(k), k=1, 9 states, 1 adaptive escapes // table 5 (decision 3): LL(k), k=1, 9 states, 1 adaptive escapes // table 6 (decision 3): LL(k), k=0, 1 states // table 7 (decision 7): LL(k), k=1, 9 states @@ -1700,7 +1700,7 @@ static _serializedATN: [&'static str; 19] = [ "ODxEVmxwiAEKEhIAEjAABAEEBAEBBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", "EBYOGhoQBAYMAAIEAAAAAAwMDAQEAgYGBAwGDAACBAAAAAAMDAwQEgIUFgQQGkgABgAEAgICAgICAgII", "AAACAAAAAAAAAAAAAAASEkhISEhISEhISEhIGBgCHh4EICAGAQEIAgIKBAQMBgYOCAgQCg4SEBYUGhoW", - "HBwYARIwAAQEAQEEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAES", + "HBwYARIwAAQEAQIEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAES", "MAAEBAEEBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4aGhABAgAEAAAA", "ARIwAAQEBAQEBAIEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAEUNgAE", "BAQEBAQBBAQEAAAAAAAAAAAAADY2NjY2NjY2NjYBAQICAgQEBAYGBggICAoKDgwQEg4UFhAaGhIEBgQC", diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index b3f5765ce6..51a25cb552 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -15,8 +15,10 @@ import org.antlr.v4.runtime.atn.EmptyPredictionContext; import org.antlr.v4.runtime.atn.LoopEndState; import org.antlr.v4.runtime.atn.NotSetTransition; +import org.antlr.v4.runtime.atn.PlusBlockStartState; import org.antlr.v4.runtime.atn.PrecedencePredicateTransition; import org.antlr.v4.runtime.atn.PredicateTransition; +import org.antlr.v4.runtime.atn.StarBlockStartState; import org.antlr.v4.runtime.atn.PredictionContext; import org.antlr.v4.runtime.atn.PredictionMode; import org.antlr.v4.runtime.atn.RuleStopState; @@ -343,9 +345,9 @@ public Result(DecisionState decisionState) { protected int precClassLo, precClassHi; /** - * ATN states of the operator loop block of the left-recursive rule - * under per-precedence-class construction (the star-loop entry's - * iterate branch, rule-local: operand rule references contribute + * ATN states of the left-recursive rule's body under per-precedence- + * class construction (rule-local: base alternatives, operand descent + * follow states, and the operator loop; rule references contribute * their follow states, not their bodies). Token consumption at these * states - or in a rule invoked from them (a loop-block return state * in the calling context) - is "loop consumption"; everything else a @@ -355,18 +357,25 @@ public Result(DecisionState decisionState) { protected java.util.BitSet precLoopStates; /** - * ATN states of the precedence rule from which its stop state is - * reachable by epsilon transitions alone (rule references block: a - * pending operand or operator is an unmet obligation). A phantom - * enclosing frame of the enter/exit substitution argument must carry - * no such obligation at resolution time - a plain binary operator - * loop is completable right after its operand, but a compound - * alternative like {@code expr (',' expr)* '>>' expr} still owes its - * {@code '>>'} after a comma operand, and there the runtime can kill - * the iterate alternative with deeper lookahead and legitimately - * predict exit. + * ATN states of the precedence rule with an outgoing token-matching + * transition - a pending token obligation. */ - protected java.util.BitSet precCompletableStates; + protected java.util.BitSet precTokenObligatedStates; + + /** + * ATN states of the precedence rule that can reach a token match by + * epsilon without passing through the loop decision: positions owing + * a token of the current alternative (the reverse-epsilon + * closure of {@link #precTokenObligatedStates}, blocked at the + * decision state). A phantom enclosing frame at such a position owes + * something the iterate reading does not - the list element of + * {@code expr (',' expr)* '>>' expr} returns into a pending + * {@code ','}/{@code '>>'} - so the enter/exit substitution veto + * stands. A frame whose only path to a token crosses the decision + * owes exactly the next operator - which the iterate reading owes + * too - and is benign. + */ + protected java.util.BitSet precPendingStates; /** * True while building the lowest precedence class (class 0). The @@ -376,8 +385,28 @@ public Result(DecisionState decisionState) { * constant) and for no other class. */ protected boolean precClassSubstitutable; + + /** + * True when every guarded (precedence-bearing) alternative of the + * precedence rule is simple: at most one rule invocation and + * no internal iteration. The enter/exit substitution argument maps + * an enclosing frame's "operator consumed, operand in progress" onto + * the inner loop's iterate - valid only when the operand completes + * the alternative's recursive structure. A compound alternative like + * {@code expr (',' expr)* '>>' expr} breaks it: the iterate reading + * of {@code a,c>>x} completes the inner Send as a list element and + * then dies (the outer Send's '>>' is missing), while the exit + * reading completes the sentence - adaptive predicts exit, so the + * substitution must not fire. Detected empirically: accepting + * iterate there produced (expr a) , ((expr c) >> (expr x)) instead + * of (expr a) , (expr c) >> (expr x). + */ + protected boolean precSimpleLoop; /** Rule index of the precedence decision under construction; -1 = none. */ protected int precRuleIndex = -1; + + /** Decision under construction (debug filtering for closure traces). */ + protected int currentDecisionNumber = -1; /** During precedence-mode construction: exact conflicts are not trusted. */ protected boolean trustExactAmbig = true; /** @@ -540,18 +569,23 @@ protected Result classifyPrecedence(DecisionState s) { callByFollowState(); - // The operator loop block: rule-local BFS along the iterate branch - // of the star-loop entry (transition 0); rule references contribute - // their follow states (operand bodies are foreign rules reached - // with a loop-block frame in the context instead). The exit branch - // (transition 1) and everything past it stay outside. + // The operator loop block: every rule-local position of the + // transformed left-recursive rule - base alternatives, the operand + // descent follow states, and the operator loop. Rule references + // contribute their follow states (operand bodies are foreign rules + // reached with a loop-block frame in the context instead). The + // block is entered from the rule start: rooting the BFS at the + // loop's iterate branch alone missed the base-operand descent, so + // consumption inside a nested invocation's operand (the follow + // state of the base operand's rule reference) was misclassified + // foreign, vetoing the enter/exit substitution on shapes like + // `1 + 1`. this.precLoopStates = new java.util.BitSet(); Deque loopWork = new ArrayDeque(); - loopWork.add(s.transition(0).target); - ATNState loopExit = s.transition(1).target; + loopWork.add(atn.ruleToStartState[s.ruleIndex]); while (!loopWork.isEmpty()) { ATNState st = loopWork.remove(); - if (st == loopExit || st.ruleIndex != s.ruleIndex + if (st.ruleIndex != s.ruleIndex || st instanceof RuleStopState || precLoopStates.get(st.stateNumber)) { continue; @@ -564,32 +598,102 @@ protected Result classifyPrecedence(DecisionState s) { } } - // Epsilon-completability (see precCompletableStates): fixpoint over - // reverse epsilon edges from the rule's stop state. - this.precCompletableStates = new java.util.BitSet(); - RuleStopState stop = atn.ruleToStopState[s.ruleIndex]; - precCompletableStates.set(stop.stateNumber); - boolean changed = true; - while (changed) { - changed = false; - for (ATNState st : atn.states) { - if (st == null || st.ruleIndex != s.ruleIndex - || precCompletableStates.get(st.stateNumber)) { - continue; + // Token obligations and the pending-token states (see + // precTokenObligatedStates / precPendingStates). + this.precTokenObligatedStates = new java.util.BitSet(); + for (ATNState st : atn.states) { + if (st == null || st.ruleIndex != s.ruleIndex) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + if (!st.transition(i).isEpsilon()) { + precTokenObligatedStates.set(st.stateNumber); + break; } - for (int i = 0; i < st.getNumberOfTransitions(); i++) { - Transition t = st.transition(i); - if (t.isEpsilon() && !(t instanceof RuleTransition) - && precCompletableStates.get(t.target.stateNumber)) { - precCompletableStates.set(st.stateNumber); - changed = true; + } + } + // Pending-token states: can reach a token match by epsilon without + // passing through the loop decision - i.e., the token is owed by + // the current alternative, not by the next loop iteration (whose + // operators are reached only via the decision). Computed as the + // reverse-epsilon closure of token-obligated states, blocked at + // the decision state. A phantom frame at such a position owes + // something the iterate reading does not (Send's list element + // returns into a pending ','/'>>'); a frame blocked only by the + // decision owes exactly the next operator, which iterate owes too. + List> reverseEps = new ArrayList>(atn.states.size()); + for (int i = 0; i < atn.states.size(); i++) reverseEps.add(new ArrayList()); + for (ATNState st : atn.states) { + if (st == null || st.ruleIndex != s.ruleIndex) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t.isEpsilon() && !(t instanceof RuleTransition) + && t.target.ruleIndex == s.ruleIndex) { + reverseEps.get(t.target.stateNumber).add(st); + } + } + } + this.precPendingStates = new java.util.BitSet(); + Deque pendingWork = new ArrayDeque(); + for (int i = precTokenObligatedStates.nextSetBit(0); i >= 0; + i = precTokenObligatedStates.nextSetBit(i+1)) { + if (!precPendingStates.get(i)) { + precPendingStates.set(i); + pendingWork.add(atn.states.get(i)); + } + } + while (!pendingWork.isEmpty()) { + ATNState st = pendingWork.remove(); + if (st == s) continue; // do not propagate past the decision + for (ATNState pred : reverseEps.get(st.stateNumber)) { + if (!precPendingStates.get(pred.stateNumber)) { + precPendingStates.set(pred.stateNumber); + pendingWork.add(pred); + } + } + } + precPendingStates.clear(s.stateNumber); + + // Simplicity of the guarded alternatives (see precSimpleLoop): + // walk each precedence-guarded alternative's continuation. + this.precSimpleLoop = true; + for (ATNState st : atn.states) { + if (st == null || st.ruleIndex != s.ruleIndex) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (!(t instanceof PrecedencePredicateTransition)) continue; + int invocations = 0; + Set visited = new HashSet(); + Deque altWork = new ArrayDeque(); + altWork.add(t.target); + while (!altWork.isEmpty() && precSimpleLoop) { + ATNState x = altWork.remove(); + if (x == s || x.ruleIndex != s.ruleIndex || !visited.add(x)) continue; + if (x instanceof StarBlockStartState || x instanceof PlusBlockStartState) { + precSimpleLoop = false; break; } + for (int j = 0; j < x.getNumberOfTransitions(); j++) { + Transition t2 = x.transition(j); + if (t2 instanceof RuleTransition) { + if (++invocations > 1) precSimpleLoop = false; + altWork.add(((RuleTransition)t2).followState); + } + else { + altWork.add(t2.target); + } + } } + if (!precSimpleLoop) break; } } StaticDFA[] tables = new StaticDFA[reps.length]; + if (System.getProperty("antlr.dfa.debug.loopstates") != null) { + System.err.printf("LOOP-STATES d=%d rule=%s count=%d:%n", + s.decision, g.getRule(s.ruleIndex).name, precLoopStates.cardinality()); + for (int i = precLoopStates.nextSetBit(0); i >= 0; i = precLoopStates.nextSetBit(i+1)) { + System.err.printf(" %d%n", i); + } + } StringBuilder note = new StringBuilder(); boolean anyTable = false; int maxK = 0; @@ -813,6 +917,7 @@ protected Set applyPrecedenceFilter(Set raw) { /** One construction attempt at the given context-depth bound; true = overflow. */ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { this.currentDepthBound = depthBound; + this.currentDecisionNumber = s.decision; this.depthCache = new java.util.IdentityHashMap(); Map, Integer> stateIds = new HashMap, Integer>(); List> states = new ArrayList>(); @@ -898,7 +1003,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { // the runtime either way. Iterate viability itself must be // attested by a non-widened, non-foreign config so the // accept is never based on an analysis artifact alone. - if (precRuleIndex >= 0 && precClassSubstitutable && exact + if (precRuleIndex >= 0 && precClassSubstitutable && precSimpleLoop && exact && conflicting.cardinality() == 2 && conflicting.get(1) && conflicting.get(2)) { boolean exitForeign = false; @@ -909,13 +1014,24 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { if ((c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) != 0) { exitForeign = true; } - // every phantom same-rule frame of the exit - // derivation must be obligation-free: the - // config's own position if it is in the rule, - // and every same-rule return state on its - // context chain (deeper phantom frames) + // Every phantom same-rule frame of the exit + // derivation must be free of token obligations + // outside the iteration-start region. An + // operand-start position owes the operand - + // exactly what the iterate reading owes too + // (both invoke the same operand next) - UNLESS + // its invocation returns into pending tokens of + // a compound alternative: the operand of a + // simple binary/unary operator returns to the + // alternative tail (nothing pending, benign), + // but a list element of expr (',' expr)* '>>' + // expr returns to a position owing ',' or '>>', + // which has no iterate-side counterpart - there + // the runtime can kill iterate with deeper + // lookahead and legitimately predict exit. if (c.state.ruleIndex == precRuleIndex - && !precCompletableStates.get(c.state.stateNumber)) { + && precPendingStates.get(c.state.stateNumber) + && hasPendingPrecReturn(c.context)) { exitObligated = true; } if (hasObligatedReturn(c.context, @@ -934,6 +1050,25 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { acceptAlts.set(d, 1); continue; } + if ("veto".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("SUBST-VETO d=%d state=%d foreign=%s obligated=%s iterateReal=%s%n", + s.decision, d, exitForeign, exitObligated, iterateReal); + for (ATNConfig c : cs) { + if (c.alt == 2 && c.state.ruleIndex == precRuleIndex) { + ATNState st = c.state; + StringBuilder tr = new StringBuilder(); + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (i > 0) tr.append(' '); + tr.append(t.isEpsilon() ? "eps" : t.label() != null ? t.label().toString(g.getVocabulary()) : "?") + .append("->").append(t.target.stateNumber); + } + System.err.printf(" alt=2 %s:%d taint=%d transitions: %s ctx=%s%n", + g.getRule(st.ruleIndex).name, st.stateNumber, + c.reachesIntoOuterContext, tr, decodeContext(c.context)); + } + } + } } // A conflict is trusted as an exact ambiguity only if it is @@ -1060,6 +1195,11 @@ else if (abortOnUntrustedConflict) { boolean cyclic = isCyclic(edges); if (!cyclic) res.k = longestPath(edges); + if ("states".equals(System.getProperty("antlr.dfa.debug")) + && String.valueOf(currentDecisionNumber).equals(System.getProperty("antlr.dfa.debug.decision"))) { + dumpStates(s, states, edges, edgeLabels, acceptAlts, stateDepth); + } + int escapes = 0; for (int a : acceptAlts) { if (a == StaticDFA.ESCAPE) escapes++; @@ -1308,18 +1448,25 @@ else if (t instanceof WildcardTransition) { else { ATNConfig advanced = new ATNConfig(c, moveTargets.get(m)); if (precRuleIndex >= 0 - && (c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0 - && !isLoopConsumption(c)) { - // boundary-popped config consuming outside the - // operator loop: the phantom consumer is not an - // enclosing invocation of this loop - advanced.reachesIntoOuterContext |= FOREIGN_CONSUME_TAINT; - if ("full".equals(System.getProperty("antlr.dfa.debug")) - && (c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) == 0) { - System.err.printf("FOREIGN-MARK rule=%s state=%d alt=%d taint=%d ctx=%s label=%s%n", - g.getRule(c.state.ruleIndex).name, c.state.stateNumber, - c.alt, c.reachesIntoOuterContext, c.context, - labels.get(m).toString(g.getVocabulary())); + && (c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0) { + if (isLoopConsumption(c)) { + // loop-block consumption by a boundary-popped + // config: the phantom consumer is an enclosing + // invocation of this loop (kept untainted so + // the enter/exit substitution can fire) + } + else { + // boundary-popped config consuming outside the + // operator loop: the phantom consumer is not an + // enclosing invocation of this loop + advanced.reachesIntoOuterContext |= FOREIGN_CONSUME_TAINT; + if ("full".equals(System.getProperty("antlr.dfa.debug")) + && (c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) == 0) { + System.err.printf("FOREIGN-MARK rule=%s state=%d alt=%d taint=%d ctx=%s label=%s%n", + g.getRule(c.state.ruleIndex).name, c.state.stateNumber, + c.alt, c.reachesIntoOuterContext, c.context, + labels.get(m).toString(g.getVocabulary())); + } } } closure(advanced, succ, busy, res, 0); @@ -1540,9 +1687,33 @@ protected boolean isLoopConsumption(ATNConfig c) { } /** - * Does the context chain contain a same-rule return state that is not - * epsilon-completable - a phantom frame of the precedence rule with an - * unmet obligation (see {@link #precCompletableStates})? + * Does the context's top-level frame chain contain a same-rule return + * state with an outgoing token transition - i.e., is this re-entered + * operand's result awaited by pending tokens of a compound + * alternative (like the ','/'>>' after a list element), rather than + * an alternative tail (the operand of a simple operator, after which + * the alternative is complete)? + */ + private boolean hasPendingPrecReturn(PredictionContext ctx) { + if (ctx == null || ctx.isEmpty()) return false; + for (int i = 0; i < ctx.size(); i++) { + int rs = ctx.getReturnState(i); + if (rs != PredictionContext.EMPTY_RETURN_STATE) { + ATNState st = atn.states.get(rs); + if (st.ruleIndex == precRuleIndex + && precPendingStates.get(rs)) { + return true; + } + } + } + return false; + } + + /** + * Does the context chain contain a same-rule return state with a + * token obligation outside the iteration-start region - a phantom + * frame of the precedence rule that cannot be discharged by iterating + * (see {@link #precPendingStates})? */ private boolean hasObligatedReturn(PredictionContext ctx, Set visited) { if (ctx == null || ctx.isEmpty() || !visited.add(ctx)) return false; @@ -1551,7 +1722,7 @@ private boolean hasObligatedReturn(PredictionContext ctx, Set if (rs != PredictionContext.EMPTY_RETURN_STATE) { ATNState st = atn.states.get(rs); if (st.ruleIndex == precRuleIndex - && !precCompletableStates.get(rs)) { + && precPendingStates.get(rs)) { return true; } if (hasObligatedReturn(ctx.getParent(i), visited)) return true; @@ -1572,6 +1743,54 @@ private boolean hasLoopReturn(PredictionContext ctx, Set visi return false; } + /** + * Debug dump (-Dantlr.dfa.debug=states -Dantlr.dfa.debug.decision=N): + * every constructed DFA state of decision N with depth, accept, edges + * (token names), and configs decoded to rule names; context return + * states are decoded via callByFollowState to the invoked rule. + */ + protected void dumpStates(DecisionState s, List> states, + List> edges, List> edgeLabels, + List acceptAlts, List stateDepth) { + System.err.printf("=== DFA states d=%d class=[%d,%d] rep=%d ===%n", + s.decision, precClassLo, precClassHi, precEvalValue); + for (int i = 0; i < states.size(); i++) { + StringBuilder edgeStr = new StringBuilder(); + for (int e = 0; e < edges.get(i).size(); e++) { + if (e > 0) edgeStr.append(' '); + edgeStr.append(edgeLabels.get(i).get(e).toString(g.getVocabulary())) + .append("->").append(edges.get(i).get(e)); + } + System.err.printf("state %d depth=%d accept=%d edges: %s%n", + i, stateDepth.get(i), acceptAlts.get(i), edgeStr); + for (ATNConfig c : states.get(i)) { + System.err.printf(" alt=%d %s:%d taint=%d ctx=%s%n", + c.alt, g.getRule(c.state.ruleIndex).name, c.state.stateNumber, + c.reachesIntoOuterContext, decodeContext(c.context)); + } + } + } + + /** Decode a context's return states to invoked-rule names for dumps. */ + protected String decodeContext(PredictionContext ctx) { + if (ctx == null || ctx.isEmpty()) return "$"; + StringBuilder sb = new StringBuilder("["); + for (int i = 0; i < ctx.size(); i++) { + if (i > 0) sb.append(", "); + int rs = ctx.getReturnState(i); + if (rs == PredictionContext.EMPTY_RETURN_STATE) { + sb.append("$"); + } + else { + RuleTransition call = callByFollowState().get(rs); + sb.append(call != null ? g.getRule(call.target.ruleIndex).name : "?") + .append('@').append(rs) + .append(' ').append(decodeContext(ctx.getParent(i))); + } + } + return sb.append(']').toString(); + } + /** Does a return state appear anywhere in a (possibly DAG-shaped) context? */ protected static boolean hasReturnState(PredictionContext ctx, int returnStateNumber) { return hasReturnState(ctx, returnStateNumber, From 0316a84d6e3790db15734b76aa4d9aa373fcbb0a Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 17 Jul 2026 13:22:42 -0400 Subject: [PATCH 11/48] Pending tokens must be unskippable: Duckdb 1+1 resolves in-table The pending-token obligation check treated every epsilon-reachable token as owed, but an OPTIONAL trailing token is not an obligation - the phantom frame can skip it. Duckdb's valueExpression base alternative (primaryExpression '(+)'?) was exactly that shape, vetoing the enter/exit substitution on every simple arithmetic expression. Pending is now computed as unskippability: positions that cannot reach the loop decision by epsilon alone. An optional marker position skips freely (benign); Send's list-star exit still cannot proceed without its '>>' (veto preserved). Duckdb, Rust, 20k parses each: - SELECT 1 + 1 FROM MY_TABLE: 6.1us -> 2.6us (2.3x), zero escapes (was: parity with adaptive, 1 escape/parse) - SELECT T1.C1, ..., T4.C4 FROM MY_TABLE: still parity - 12 escapes/parse remain in the function-call postfix loop (guarded alternatives with argument-list iteration: the substitution stays conservatively off per the Send evidence), the selectItem alias decision, and the primary base decision's identifier ambiguity. Verified: cargo 55/55, runtime suites 707/707, tool-testsuite 694, B4 17/17, Send 9/9, p1probe 24/24, lrdfa 8/8, Trino 1+1 still 0 escapes, all six SQL grammars fully table-first. Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 51a25cb552..e2d567a09d 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -610,15 +610,16 @@ protected Result classifyPrecedence(DecisionState s) { } } } - // Pending-token states: can reach a token match by epsilon without - // passing through the loop decision - i.e., the token is owed by - // the current alternative, not by the next loop iteration (whose - // operators are reached only via the decision). Computed as the - // reverse-epsilon closure of token-obligated states, blocked at - // the decision state. A phantom frame at such a position owes - // something the iterate reading does not (Send's list element - // returns into a pending ','/'>>'); a frame blocked only by the - // decision owes exactly the next operator, which iterate owes too. + // Pending-token states: positions that CANNOT reach the loop + // decision by epsilon alone - every continuation owes a token of + // the current alternative. The complement set (states that skip + // to the decision freely) owes nothing: an optional trailing + // token like the '(+)'? of Duckdb's valueExpression base + // alternative is not an obligation, but Send's '>>' is - the + // list-star exit of expr (',' expr)* '>>' expr cannot proceed + // without it. A phantom frame at a pending position has no + // iterate-side counterpart (the veto stands); a frame that can + // skip owes exactly the next operator, which iterate owes too. List> reverseEps = new ArrayList>(atn.states.size()); for (int i = 0; i < atn.states.size(); i++) reverseEps.add(new ArrayList()); for (ATNState st : atn.states) { @@ -631,26 +632,27 @@ protected Result classifyPrecedence(DecisionState s) { } } } - this.precPendingStates = new java.util.BitSet(); - Deque pendingWork = new ArrayDeque(); - for (int i = precTokenObligatedStates.nextSetBit(0); i >= 0; - i = precTokenObligatedStates.nextSetBit(i+1)) { - if (!precPendingStates.get(i)) { - precPendingStates.set(i); - pendingWork.add(atn.states.get(i)); + java.util.BitSet epsSkip = new java.util.BitSet(); + Deque skipWork = new ArrayDeque(); + epsSkip.set(s.stateNumber); + skipWork.add(s); + while (!skipWork.isEmpty()) { + ATNState cur = skipWork.remove(); + for (ATNState pred : reverseEps.get(cur.stateNumber)) { + if (!epsSkip.get(pred.stateNumber)) { + epsSkip.set(pred.stateNumber); + skipWork.add(pred); + } } } - while (!pendingWork.isEmpty()) { - ATNState st = pendingWork.remove(); - if (st == s) continue; // do not propagate past the decision - for (ATNState pred : reverseEps.get(st.stateNumber)) { - if (!precPendingStates.get(pred.stateNumber)) { - precPendingStates.set(pred.stateNumber); - pendingWork.add(pred); - } + this.precPendingStates = new java.util.BitSet(); + for (ATNState st : atn.states) { + if (st != null && st.ruleIndex == s.ruleIndex + && !(st instanceof RuleStopState) + && !epsSkip.get(st.stateNumber)) { + precPendingStates.set(st.stateNumber); } } - precPendingStates.clear(s.stateNumber); // Simplicity of the guarded alternatives (see precSimpleLoop): // walk each precedence-guarded alternative's continuation. From bb6ec1bdbce65c4c11110490230d1c1e42de8dec Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 17 Jul 2026 14:55:14 -0400 Subject: [PATCH 12/48] Decision report: per-decision adaptivePredict-fallback (fb) breakout The category summary was deceptive under the hybrid scheme: a decision marked static could still carry hybrid escape states or adaptive precedence classes that hand individual predictions back to the adaptive engine at runtime. The report now shows the true fallback structure: - per decision, an fb column: 0 (no prediction can reach adaptivePredict: pure LL(1) or complete table), all (no table), N (escape states of a hybrid table), Ne+Mc (precedence decisions: escape states + classes without tables); - a grammar-level fallbacks line: static-only decisions/total, total escape states and how many hybrid decisions carry them, adaptive precedence classes, and decisions with no table at all. Current picture across the six SQL grammars: grammar decisions static-only escapes (hybrid decisions) adaptive-only Trino 415 355 1367 (60) 0 Bigquery 450 420 746 (30) 0 Databricks 520 424 4394 (96) 0 Duckdb 529 429 4932 (100) 0 Redshift 486 397 3663 (89) 0 Snowflake 786 695 3829 (91) 0 Every prediction in every grammar is table-first (zero adaptive-only decisions, zero adaptive precedence classes); all fallbacks are per-state hybrid escapes. Escape-heavy decisions are the known cold corners: Trino valueExpression fb=90e, primaryExpression fb=56e, booleanExpression fb=2e - the lambda/BETWEEN shapes the adaptive engine owns by design, invisible to simple arithmetic (0 escapes on SELECT 1 + 1 despite fb=90e on the loop). Signed-off-by: Bo Lin --- tool/src/org/antlr/v4/Tool.java | 2 +- .../antlr/v4/analysis/DecisionClassifier.java | 69 ++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index 63e457dc19..fa910c1758 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -139,7 +139,7 @@ public Option(String fieldName, String name, OptionArgType argType, String descr new Option("force_atn", "-Xforce-atn", "use the ATN simulator for all predictions"), new Option("log", "-Xlog", "dump lots of logging info to antlr-timestamp.log"), new Option("exact_output_dir", "-Xexact-output-dir", "all output goes into -o dir regardless of paths/package"), - new Option("decision_report", "-Xdecision-report", "classify every parser decision by required static lookahead (LL(1)/LL(k)/LL(*)/ambiguous/context-sensitive) and print a report"), + new Option("decision_report", "-Xdecision-report", "classify every parser decision by required static lookahead (LL(1)/LL(k)/LL(*)/ambiguous/context-sensitive) and print a report with a per-decision adaptivePredict-fallback (fb) breakout"), new Option("static_dfa", "-Xstatic-dfa", "precompute SLL prediction DFAs and generate table-driven prediction instead of adaptivePredict where provably behavior-preserving (Java/Rust targets)"), }; diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index e2d567a09d..4168cbbb87 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -161,6 +161,9 @@ public static class Result { public String precNote; /** For HYBRID tables: number of escape states. */ public int escapes; + /** For LR_PRECEDENCE decisions: precedence classes without a table + * (their dispatch entry defers to adaptivePredict). */ + public int adaptiveClasses; /** * For HYBRID tables: fraction of the start state's outgoing token * space whose successor subgraph contains at least one accept @@ -735,6 +738,7 @@ protected Result classifyPrecedence(DecisionState s) { : c < cutoffs.length ? "=" + (cutoffs[c-1]+1) + ".." + cutoffs[c] : ">" + cutoffs[cutoffs.length-1]).append(':'); if (attempt.dfa == null) { + res.adaptiveClasses++; if (attempt.category == Category.HYBRID) { // hybrid construction worked but fell below the // coverage floor; the class stays adaptive @@ -1942,6 +1946,36 @@ public static String report(Grammar g) { if (r.precDfa != null) precStatic++; } + // Runtime adaptivePredict fallback accounting: the table categories + // alone are deceptive - a "static" decision may still carry hybrid + // escape states or adaptive precedence classes that hand individual + // predictions back to the adaptive engine at runtime. + int fbStaticOnly = 0, fbEscapeStates = 0, fbHybridDecisions = 0; + int fbAdaptiveClasses = 0, fbAdaptiveOnly = 0; + for (Result r : results) { + if (r.category == Category.LR_PRECEDENCE) { + if (r.precDfa == null) { + fbAdaptiveOnly++; + } + else { + fbEscapeStates += r.escapes; + fbAdaptiveClasses += r.adaptiveClasses; + if (r.escapes > 0) fbHybridDecisions++; + else if (r.adaptiveClasses == 0) fbStaticOnly++; + } + } + else if (r.category == Category.LL1 || (r.dfa != null && r.escapes == 0)) { + fbStaticOnly++; + } + else if (r.dfa == null) { + fbAdaptiveOnly++; + } + else { + fbHybridDecisions++; + fbEscapeStates += r.escapes; + } + } + StringBuilder buf = new StringBuilder(); buf.append("=== decision report: grammar ").append(g.name) .append(" (").append(results.size()).append(" decisions) ===\n"); @@ -1955,6 +1989,11 @@ public static String report(Grammar g) { } } buf.append('\n'); + buf.append(String.format( + "fallbacks: static-only=%d/%d; escape-states=%d across %d hybrid decisions" + + " + %d adaptive precedence classes; adaptive-only decisions=%d%n", + fbStaticOnly, results.size(), fbEscapeStates, fbHybridDecisions, + fbAdaptiveClasses, fbAdaptiveOnly)); int maxKAnyAcyclic = 0; int maxKLLK = 0; @@ -1967,7 +2006,8 @@ public static String report(Grammar g) { buf.append(String.format("%-22s d=%-4d %-17s", lrRule.name, r.decisionState.decision, r.category)); buf.append(' ').append(r.precNote) - .append(r.precDfa != null ? " [static]" : " [adaptive]").append('\n'); + .append(r.precDfa != null ? " [static]" : " [adaptive]") + .append(" fb=").append(fbString(r)).append('\n'); } continue; } @@ -1978,6 +2018,7 @@ public static String report(Grammar g) { } Rule rule = g.getRule(r.decisionState.ruleIndex); buf.append(String.format("%-22s d=%-4d %-17s", rule.name, r.decisionState.decision, r.category)); + buf.append(" fb=").append(fbString(r)); if (r.k >= 0) buf.append(" k=").append(r.k); buf.append(" dfaStates=").append(r.numDfaStates); if (r.category == Category.HYBRID) { @@ -2007,6 +2048,32 @@ public static String report(Grammar g) { return buf.toString(); } + /** + * Runtime-fallback descriptor of a decision: "0" when no prediction of + * this decision can reach adaptivePredict (pure LL(1) code or a + * complete static table); "all" when the decision has no table at all + * (fully adaptive); otherwise the number of table states that defer to + * the adaptive engine - escape states of a hybrid table ("N"), and for + * precedence-dispatched decisions escape states plus classes without + * tables ("Ne+Mc"). + */ + private static String fbString(Result r) { + if (r.category == Category.LR_PRECEDENCE) { + if (r.precDfa == null) return "all"; + if (r.escapes == 0 && r.adaptiveClasses == 0) return "0"; + StringBuilder s = new StringBuilder(); + if (r.escapes > 0) s.append(r.escapes).append('e'); + if (r.adaptiveClasses > 0) { + if (s.length() > 0) s.append('+'); + s.append(r.adaptiveClasses).append('c'); + } + return s.toString(); + } + if (r.category == Category.LL1) return "0"; + if (r.dfa == null) return "all"; + return r.escapes > 0 ? String.valueOf(r.escapes) : "0"; + } + private static Set distinct(List sets) { return new LinkedHashSet(sets); } From dcaa6ec7bff2628160790b50f190d3087db47661 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 17 Jul 2026 17:02:43 -0400 Subject: [PATCH 13/48] Codegen: emit the adaptive fallback only where it can fire Generated parsers wrapped every dfa_predict call site with an adaptive_predict fallback, even for decisions whose tables are complete (no escape states, no adaptive classes) - dead code at every such site, and it made the generated files misleading as an audit of the fallback structure (betweenexprparser.rs showed 8 adaptivePredict sites while only 3 decisions can actually defer). The Choice model now carries tableCanDefer, computed from the tables: true for precedence-dispatched decisions (they additionally defer at the entry frame - when the left-recursive rule itself is the parse entry - regardless of escapes) and for any table with escape states or classes without tables; false for plain complete tables. The Rust staticDFAPredict template emits the bare walker for the latter. BetweenExpr: 5 of 8 sites keep the fallback (d=0 hybrid; d=3, d=7 dispatched with hybrid/adaptive classes), d=2/d=6/d=8 go bare. Trino: 82 of 206 sites keep it (124 dead wrappers removed). A/B benchmark of the two template forms on identical tables: 4.32-4.54us vs 4.29-4.32us on the multi-column query - perf-neutral. Verified: cargo 55/55 (incl. both differential suites), runtime suites 707/707, tool-testsuite 694, B4 17/17, Send 9/9. Signed-off-by: Bo Lin --- runtime/Rust/tests/gen/betweenexprparser.rs | 6 ++-- runtime/Rust/tests/gen/fuzzexprparser.rs | 8 +++--- runtime/Rust/tests/gen/lrdfaparser.rs | 2 +- runtime/Rust/tests/gen/staticdfaparser.rs | 14 +++++----- .../v4/tool/templates/codegen/Rust/Rust.stg | 12 ++++---- .../v4/analysis/PrecedenceStaticDFA.java | 9 ++++++ tool/src/org/antlr/v4/analysis/StaticDFA.java | 9 ++++++ .../org/antlr/v4/codegen/ParserFactory.java | 28 +++++++++++++++++-- .../org/antlr/v4/codegen/model/Choice.java | 7 +++++ 9 files changed, 73 insertions(+), 22 deletions(-) diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index 734bec3ff0..9134a86243 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -889,7 +889,7 @@ where { recog.base.set_state(28); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(2)?; _sdp } { 1 =>{ { /*recRuleLabeledAltStartAction*/ @@ -1432,7 +1432,7 @@ where { recog.base.set_state(54); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(6)?; _sdp } { 1 =>{ { /*recRuleAltStartAction*/ @@ -1606,7 +1606,7 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(68); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(8)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(8,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(8)?; _sdp } { 1 =>{ /*------- Outer Most Alt 1 -------*/ unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index 060cd64130..ca2ec64295 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -710,7 +710,7 @@ where recog.name()?; recog.base.set_state(39); recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; while { _alt!=2 && _alt!=INVALID_ALT } { if _alt==1 { { @@ -725,7 +725,7 @@ where } recog.base.set_state(41); recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; } } Ok(()) @@ -873,7 +873,7 @@ where { recog.base.set_state(62); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(5)?; _sdp } { 1 =>{ { /*recRuleAltStartAction*/ @@ -1094,7 +1094,7 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(86); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(9)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(9,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(9)?; _sdp } { 1 =>{ /*------- Outer Most Alt 1 -------*/ unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } diff --git a/runtime/Rust/tests/gen/lrdfaparser.rs b/runtime/Rust/tests/gen/lrdfaparser.rs index 1c1bba2f9c..37cfddf3a2 100644 --- a/runtime/Rust/tests/gen/lrdfaparser.rs +++ b/runtime/Rust/tests/gen/lrdfaparser.rs @@ -1341,7 +1341,7 @@ where { recog.base.set_state(36); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(1)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(1,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(1)?; _sdp } { 1 =>{ { /*recRuleLabeledAltStartAction*/ diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index c4d9d4a164..4f51444836 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -588,7 +588,7 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(23); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(0)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(0,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(0)?; _sdp } { 1 =>{ /*------- Outer Most Alt 1 -------*/ recog.base.with_mut_ctx(|ctx| { @@ -946,7 +946,7 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(30); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(1)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(1,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(1)?; _sdp } { 1 =>{ /*------- Outer Most Alt 1 -------*/ recog.base.with_mut_ctx(|ctx| { @@ -1206,7 +1206,7 @@ where { recog.base.set_state(44); recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; while { _alt!=2 && _alt!=INVALID_ALT } { if _alt==1 { { @@ -1220,7 +1220,7 @@ where } recog.base.set_state(46); recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; } recog.base.set_state(47); recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; @@ -1341,7 +1341,7 @@ where } recog.base.set_state(54); recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(4)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(4,&mut recog.base)? } else { _sdp } }; + _alt = { let _sdp = recog.base.dfa_predict(4)?; _sdp }; if _alt==2 || _alt==INVALID_ALT { break } } recog.base.set_state(56); @@ -1445,7 +1445,7 @@ where { recog.base.set_state(61); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(5)?; _sdp } { x if x == 1 =>{ { recog.base.set_state(59); @@ -1758,7 +1758,7 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(70); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(6)?; _sdp } { 1 =>{ /*------- Outer Most Alt 1 -------*/ recog.base.with_mut_ctx(|ctx| { diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index 3a3b1af49c..b1f5d1ae74 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -770,11 +770,13 @@ loop { // carried inside the serialized ATN blob (see SerializedBase64ATN) and // decoded together with the ATN into its static_dfas field. -// The static-table prediction with the hybrid-escape fallback: a table may -// return INVALID_ALT to defer the prediction (an escape state of a partial -// table, or a precedence class without a table); the decision then reruns -// through adaptive_predict - sound because dfa_predict never consumes input. -staticDFAPredict(choice) ::= "{ let _sdp = .base.dfa_predict()?; if _sdp == INVALID_ALT { .get_interpreter().adaptive_predict(,&mut .base)? } else { _sdp } }" +// The static-table prediction, with the hybrid-escape fallback only where +// the decision can actually defer (choice.tableCanDefer: escape states of +// a partial table, or a precedence class without a table - the decision +// then reruns through adaptive_predict, sound because dfa_predict never +// consumes input). Decisions with complete tables get the bare walker; +// the fallback would be dead code. +staticDFAPredict(choice) ::= "{ let _sdp = .base.dfa_predict()?; if _sdp == INVALID_ALT { .get_interpreter().adaptive_predict(,&mut .base)? } else { _sdp }_sdp }" DFAAltBlock(choice, preamble, alts, error) ::= << .base.set_state(); diff --git a/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java b/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java index 3ebd07ac08..7c33336264 100644 --- a/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java +++ b/tool/src/org/antlr/v4/analysis/PrecedenceStaticDFA.java @@ -47,4 +47,13 @@ public PrecedenceStaticDFA(int decision, int[] cutoffs, StaticDFA[] tables) { this.cutoffs = cutoffs; this.tables = tables; } + + /** True if any precedence class has no table (dispatches to + * {@code adaptivePredict}) or has a table with escape states. */ + public boolean hasFallbacks() { + for (StaticDFA t : tables) { + if (t == null || t.hasEscapes()) return true; + } + return false; + } } diff --git a/tool/src/org/antlr/v4/analysis/StaticDFA.java b/tool/src/org/antlr/v4/analysis/StaticDFA.java index 104a183227..72811adaa4 100644 --- a/tool/src/org/antlr/v4/analysis/StaticDFA.java +++ b/tool/src/org/antlr/v4/analysis/StaticDFA.java @@ -35,6 +35,15 @@ public class StaticDFA { */ public static final int ESCAPE = -1; + /** True if any state of this table is an escape state: a runtime + * prediction driven by it can defer to {@code adaptivePredict}. */ + public boolean hasEscapes() { + for (int a : accepts) { + if (a == ESCAPE) return true; + } + return false; + } + public final int decision; public final int numStates; /** Predicted alternative per state; 0 = not an accept state; {@link #ESCAPE} = escape. */ diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index c92962c4ad..ff7da3058b 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -205,6 +205,7 @@ public Choice getChoiceBlock(BlockAST blkAST, List alts, Gramma } else if ( hasStaticDFA(decision) ) { c = new DFAAltBlock(this, blkAST, alts); + c.tableCanDefer = staticDFACanDefer(decision); } else { c = getComplexChoiceBlock(blkAST, alts); @@ -244,7 +245,7 @@ else if ( ebnfRoot.getType()==ANTLRParser.CLOSURE ) { } if ( hasStaticDFA(decision) ) { - return getDFAEBNFBlock(ebnfRoot, alts); + return getDFAEBNFBlock(ebnfRoot, alts, decision); } } @@ -261,8 +262,28 @@ protected boolean hasStaticDFA(int decision) { || (g.staticPrecedenceDFAs!=null && g.staticPrecedenceDFAs.containsKey(decision)); } + /** + * Can the static table of the given decision defer a prediction to + * adaptivePredict at runtime? Only reachable for decisions with + * {@link #hasStaticDFA}; call sites of decisions where this is false + * need no adaptive fallback wrapper. True for every precedence- + * dispatched decision: beyond escape states and table-less classes, + * the runtime defers them whenever the left-recursive rule itself is + * the parse entry (per-class tables are built against the rule's call + * sites, which an entry invocation doesn't have). + */ + protected boolean staticDFACanDefer(int decision) { + if ( g.staticPrecedenceDFAs != null + && g.staticPrecedenceDFAs.containsKey(decision) ) { + return true; + } + org.antlr.v4.analysis.StaticDFA dfa = + g.staticDecisionDFAs != null ? g.staticDecisionDFAs.get(decision) : null; + return dfa != null && dfa.hasEscapes(); + } + /** Like getComplexEBNFBlock but driving the decision from a static DFA table. */ - protected Choice getDFAEBNFBlock(GrammarAST ebnfRoot, List alts) { + protected Choice getDFAEBNFBlock(GrammarAST ebnfRoot, List alts, int decision) { int ebnf = 0; if ( ebnfRoot!=null ) ebnf = ebnfRoot.getType(); Choice c = null; @@ -277,6 +298,9 @@ protected Choice getDFAEBNFBlock(GrammarAST ebnfRoot, List alts c = new DFAPlusBlock(this, ebnfRoot, alts); break; } + if ( c != null ) { + c.tableCanDefer = staticDFACanDefer(decision); + } return c; } diff --git a/tool/src/org/antlr/v4/codegen/model/Choice.java b/tool/src/org/antlr/v4/codegen/model/Choice.java index 614f0e50f6..c895f5ff98 100644 --- a/tool/src/org/antlr/v4/codegen/model/Choice.java +++ b/tool/src/org/antlr/v4/codegen/model/Choice.java @@ -31,6 +31,13 @@ */ public abstract class Choice extends RuleElement { public int decision = -1; + /** + * For table-driven (DFA*) choices: can the static table defer a + * prediction to adaptivePredict at runtime (escape states or + * table-less precedence classes)? When false the generated call site + * skips the adaptive fallback wrapper - it would be dead code. + */ + public boolean tableCanDefer; public Decl label; @ModelElement public List alts; From ca54106dbe51655d72cffe70be45dc106c7a0502 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 18 Jul 2026 14:21:01 -0400 Subject: [PATCH 14/48] Enter/exit substitution without exactness, in every precedence class: operator loops resolve in-table The enter/exit substitution (resolve a precedence loop's iterate/exit conflict statically to iterate) no longer requires an exact conflict and is no longer restricted to class 0. Iterate viability on the shared prefix attests the operator guard passes at the current precedence, and the iterate lineage can always take the free loop-exit and rejoin exactly the caller continuation the exit lineage heads for, so exit never becomes uniquely viable in any class; the foreign- consumption, pending-obligation, and attested-real-iterate vetoes remain the load-bearing conditions. ExprLoops repro: value loop fully static in all 6 classes. All seven SQL dialects improve (Duckdb -263, Databricks -275, Redshift -267, Snowflake -87, Trino -54, Bigquery -32 escapes). Operator chains that escaped on every operator now parse in-table: A || B * C 30us -> 2.7us, A + B*C - D/E 63us -> 3.4us (11-19x vs adaptive). Send-T witness and postfix compound alternatives stay vetoed, by design. Divergence note: on invalid inputs where adaptivePredict throws NoViableAltException at a substituted conflict state, the static table commits to iterate and the parser reports at the match site instead - same error position, different message/recovery tree. Valid-input behavior is unchanged (the resolution above); this divergence class was already inherent to the class-0 substitution. Signed-off-by: Bo Lin --- runtime/Rust/tests/gen/betweenexprparser.rs | 4 +- .../antlr/v4/analysis/DecisionClassifier.java | 56 +++++++++++++------ 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index 9134a86243..ace01529bc 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -1681,7 +1681,7 @@ where // table 5 (decision 3): LL(k), k=1, 9 states, 1 adaptive escapes // table 6 (decision 3): LL(k), k=0, 1 states // table 7 (decision 7): LL(k), k=1, 9 states -// table 8 (decision 7): LL(k), k=1, 10 states, 1 adaptive escapes +// table 8 (decision 7): LL(k), k=1, 10 states static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); @@ -1703,6 +1703,6 @@ static _serializedATN: [&'static str; 19] = [ "HBwYARIwAAQEAQIEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAES", "MAAEBAEEBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4aGhABAgAEAAAA", "ARIwAAQEBAQEBAIEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAEUNgAE", - "BAQEBAQBBAQEAAAAAAAAAAAAADY2NjY2NjY2NjYBAQICAgQEBAYGBggICAoKDgwQEg4UFhAaGhIEBgQC", + "BAQEBAQCBAQEAAAAAAAAAAAAADY2NjY2NjY2NjYBAQICAgQEBAYGBggICAoKDgwQEg4UFhAaGhIEBgQC", "BAgKDA4EBAYOEAw=" ]; \ No newline at end of file diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 4168cbbb87..4b6bfc1bea 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -381,11 +381,20 @@ public Result(DecisionState decisionState) { protected java.util.BitSet precPendingStates; /** - * True while building the lowest precedence class (class 0). The - * enter/exit substitution argument requires every operator guard of - * the rule to pass at the class's entry precedences, which holds for - * class 0 by construction (its upper bound is the smallest guard - * constant) and for no other class. + * True while building any precedence class in which the enter/exit + * substitution may fire. The substitution maps an exit derivation + * (an enclosing frame of the same loop consumes the operator) onto + * an iterate derivation of the same sentence. The mapping requires + * the operator's guard to pass at the inner precedence - which the + * conflict itself attests: iterate is viable on the shared lookahead + * prefix only when an enabled alternative consumes it. Precedence + * gaps between the outer frame and the inner class do not matter: + * the iterate lineage can always take the free loop-exit and rejoin + * exactly the caller continuation the exit lineage heads for, so + * exit never becomes uniquely viable in any class. The substitution + * is therefore no longer restricted to class 0; the load-bearing + * conditions are the per-conflict vetoes (foreign consumption, + * pending obligations, attested real iterate). */ protected boolean precClassSubstitutable; @@ -710,7 +719,7 @@ protected Result classifyPrecedence(DecisionState s) { this.precEvalValue = reps[c]; this.precClassLo = reps[c]; this.precClassHi = c < cutoffs.length ? cutoffs[c] : Integer.MAX_VALUE; - this.precClassSubstitutable = c == 0; + this.precClassSubstitutable = true; Result attempt = null; for (int depthBound : wideningDepths) { Result a = new Result(s); @@ -993,23 +1002,36 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { } BitSet conflicting = PredictionMode.getAlts(altSubsets); - // Enter/exit ambiguity of a class-0 precedence loop, resolved - // to iterate by substitution: when the exit alternative's + // Enter/exit ambiguity of a precedence loop, resolved to + // iterate by substitution: when the exit alternative's // scanned tokens were consumed exclusively by (a phantom or // real) enclosing invocation of this same operator loop - no // FOREIGN_CONSUME taint - every exit derivation of a sentence - // maps to an iterate derivation of the same sentence (the - // inner loop consumes the operators instead; all guards pass - // at class-0 entry precedences, so the mapped derivation is - // legal). Exit therefore never becomes uniquely viable, and - // whenever the adaptive engine terminates - unique iterate, - // or an exact ambiguity resolved to the minimum alternative - - // it answers iterate. Spurious (widening-born) exit + // maps to an iterate derivation of the same sentence. The + // mapping is precedence-safe: the outer reading consumes the + // operator through the same loop alternative (same guard, + // same operand precedence), and the iterate lineage can + // always take the loop-exit epsilon and rejoin exactly the + // caller continuation the exit lineage heads for - so + // whenever exit is viable, iterate is viable too. Exit + // therefore never becomes uniquely viable, and whenever the + // adaptive engine terminates - unique iterate, or an + // ambiguity resolved to the minimum alternative - it answers + // iterate. Spurious (widening-born, or phantom-only) exit // viability only adds the conflict; the resolution matches - // the runtime either way. Iterate viability itself must be + // the runtime either way. This holds in every precedence + // class, not just class 0: within a class, iterate viability + // already attests that the operator's guard passes at the + // current precedence. Iterate viability itself must be // attested by a non-widened, non-foreign config so the // accept is never based on an analysis artifact alone. - if (precRuleIndex >= 0 && precClassSubstitutable && precSimpleLoop && exact + // Exactness of the conflict is NOT required: the conflicting + // subsets diverge precisely because exit carries caller + // continuations (and outer incarnations of this loop) that + // iterate only rejoins after its free loop-exit - the + // inexact shapes are the common case in wrapper-dense + // grammars. + if (precRuleIndex >= 0 && precClassSubstitutable && precSimpleLoop && conflicting.cardinality() == 2 && conflicting.get(1) && conflicting.get(2)) { boolean exitForeign = false; From 76a0c87bec91cd43cdceb0d20406bf5217d29200 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 18 Jul 2026 19:55:16 -0400 Subject: [PATCH 15/48] Prefix factor analysis: dry-run alt-mask coverage measurement PrefixFactorAnalyzer detects prefix-factorable decision groups: alternatives sharing an identical leading element sequence (token matches and rule invocations) that ends at a rule invocation, with non-nullable pairwise LL(1)-disjoint tails and no predicates/actions in the shared region. For such groups a static prediction walker may accept with an alternative mask instead of a unique alt or an adaptive escape ("implied left-factoring"): the parser executes the shared prefix once and resolves the group with a trivial tail decision. Dry-run only: buildDFA counts the states the mask protocol would resolve and the escapes it would cure; -Xdecision-report prints per-decision and total coverage. No emitted table changes (verified: generated parsers byte-identical, cargo test green). Coverage across the seven SQL dialects: the ('(' expression) group (rowConstructor vs parenthesizedExpression, tails ',' vs ')') appears in every one; ~78 escape states curable overall, including the hot shallow states (Trino d=316's state 226, hit by every typical parenthesized expression). Debug aids under -Dantlr.dfa.debug=factor: group extraction, cure lines, terminal simulation. Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 88 ++++- .../v4/analysis/PrefixFactorAnalyzer.java | 318 ++++++++++++++++++ 2 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 tool/src/org/antlr/v4/analysis/PrefixFactorAnalyzer.java diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 4b6bfc1bea..3069d4c23d 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -175,6 +175,18 @@ public static class Result { * nothing is pure overhead. */ public double coverage; + /** + * The decision's prefix-factor plan (see + * {@link PrefixFactorAnalyzer}), populated when the decision has + * factorable groups. Dry-run for the alt-mask mechanism: no + * effect on emitted tables. + */ + public PrefixFactorAnalyzer.Plan factorPlan; + /** Dry-run: DFA states whose live-alt set is covered by one + * factor group (would accept with an alternative mask). */ + public int factorMaskStates; + /** Dry-run: escape states that a mask accept would cure. */ + public int factorEscapesCured; public Result(DecisionState decisionState) { this.decisionState = decisionState; @@ -437,10 +449,17 @@ public Result(DecisionState decisionState) { */ protected Map callByFollowState; + /** Analyzer for prefix-factorable decisions (alt-mask dry run). */ + protected final PrefixFactorAnalyzer factorAnalyzer; + /** Factor plan of the decision under construction; null when the + * decision has no groups or is a precedence loop decision. */ + protected PrefixFactorAnalyzer.Plan currentFactorPlan; + public DecisionClassifier(Grammar g) { this.g = g; this.atn = g.atn; this.allTokens = IntervalSet.of(Token.MIN_USER_TOKEN_TYPE, atn.maxTokenType); + this.factorAnalyzer = new PrefixFactorAnalyzer(g, atn); } /** Classify all decisions of the grammar, indexed by decision number. */ @@ -454,6 +473,7 @@ public List classifyAll() { public Result classify(DecisionState s) { Result res = new Result(s); + this.currentFactorPlan = null; if (s.nonGreedy) { res.category = Category.NON_GREEDY; return res; @@ -468,6 +488,16 @@ public Result classify(DecisionState s) { return res; } + // alt-mask dry run: compute the prefix-factor plan up front; the + // construction attempts count the states it would resolve. + this.currentFactorPlan = factorAnalyzer.analyze(s); + if (currentFactorPlan.hasGroups() + && "factor".equals(System.getProperty("antlr.dfa.debug"))) { + for (PrefixFactorAnalyzer.Group grp : currentFactorPlan.groups) { + System.err.printf("FACTOR d=%d %s%n", s.decision, grp.toString(g)); + } + } + // iterative deepening: exact first, then progressively wider approximation Result outcome = res; boolean allOverflowed = true; @@ -490,8 +520,12 @@ public Result classify(DecisionState s) { && (outcome.category == Category.OVERFLOW || outcome.category == Category.CONTEXT_SENSITIVE)) { Result hybrid = classifyHybrid(s); - if (hybrid != null && hybrid.dfa != null) return hybrid; + if (hybrid != null && hybrid.dfa != null) { + if (currentFactorPlan.hasGroups()) hybrid.factorPlan = currentFactorPlan; + return hybrid; + } } + if (currentFactorPlan.hasGroups()) outcome.factorPlan = currentFactorPlan; return outcome; } @@ -988,6 +1022,22 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { acceptAlts.set(d, Math.max(0, alts.nextSetBit(0))); continue; } + + // alt-mask dry run: a state whose live alternatives fall + // inside a single prefix-factor group would accept with an + // alternative mask instead of resolving further (or escaping) + PrefixFactorAnalyzer.Group factorGroup = currentFactorPlan != null + ? currentFactorPlan.groupCovering(alts) : null; + if (factorGroup != null) { + res.factorMaskStates++; + if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { + // terminal simulation: measure the mask-protocol + // table - a mask accept ends the walk, so the whole + // subtree below is never built (and never escapes) + acceptAlts.set(d, Math.max(0, alts.nextSetBit(0))); + continue; + } + } if (PredictionMode.hasSLLConflictTerminatingPrediction(PredictionMode.SLL, cs)) { Collection altSubsets = PredictionMode.getConflictingAltSubsets(cs); boolean exact = PredictionMode.allSubsetsConflict(altSubsets) @@ -1130,6 +1180,13 @@ && hasPendingPrecReturn(c.context)) { else if (hybridMode) { // the conflict cannot be resolved statically: defer // this state to adaptivePredict + if (factorGroup != null) { + res.factorEscapesCured++; + if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FACTOR-CURE d=%d state=%d depth=%d alts=%s%n", + s.decision, d, stateDepth.get(d), alts); + } + } acceptAlts.set(d, StaticDFA.ESCAPE); if (System.getProperty("antlr.dfa.debug") != null) { System.err.printf("ESCAPE-CONFLICT d=%d state=%d depth=%d exact=%s hard=%s anyB=%s allB=%s trustEA=%s alts=%s%n", @@ -1165,6 +1222,13 @@ else if (abortOnUntrustedConflict) { // first rank (bounded by the token alphabet) must not starve // its own siblings, or single-token predictions - the // dynamic majority - escape on sheer decision fanout. + if (factorGroup != null) { + res.factorEscapesCured++; + if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FACTOR-CURE-CAP d=%d state=%d depth=%d alts=%s%n", + s.decision, d, stateDepth.get(d), alts); + } + } acceptAlts.set(d, StaticDFA.ESCAPE); continue; } @@ -2017,6 +2081,22 @@ else if (r.dfa == null) { fbStaticOnly, results.size(), fbEscapeStates, fbHybridDecisions, fbAdaptiveClasses, fbAdaptiveOnly)); + // alt-mask dry run totals + int factorDecisions = 0, factorGroups = 0, factorCured = 0, factorMaskStates = 0; + for (Result r : results) { + if (r.factorPlan != null && r.factorPlan.hasGroups()) { + factorDecisions++; + factorGroups += r.factorPlan.groups.size(); + factorCured += r.factorEscapesCured; + factorMaskStates += r.factorMaskStates; + } + } + if (factorDecisions > 0) { + buf.append(String.format( + "factorable: %d decisions (%d groups); mask-accepts=%d states; escapes curable=%d%n", + factorDecisions, factorGroups, factorMaskStates, factorCured)); + } + int maxKAnyAcyclic = 0; int maxKLLK = 0; Map llkHistogram = new java.util.TreeMap(); @@ -2062,6 +2142,12 @@ else if (r.dfa == null) { ? " [widened]" : " [widened depth="+r.wideningDepth+"]"); } if (r.sawPrecPredicate) buf.append(" [precpred-in-lookahead]"); + if (r.factorPlan != null && r.factorPlan.hasGroups()) { + buf.append(" [factorable: groups=").append(r.factorPlan.groups.size()) + .append(" maskStates=").append(r.factorMaskStates) + .append(" cures=").append(r.factorEscapesCured) + .append(']'); + } buf.append('\n'); } buf.append("LLK k histogram: ").append(llkHistogram).append('\n'); diff --git a/tool/src/org/antlr/v4/analysis/PrefixFactorAnalyzer.java b/tool/src/org/antlr/v4/analysis/PrefixFactorAnalyzer.java new file mode 100644 index 0000000000..ad05413789 --- /dev/null +++ b/tool/src/org/antlr/v4/analysis/PrefixFactorAnalyzer.java @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.analysis; + +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNState; +import org.antlr.v4.runtime.atn.ActionTransition; +import org.antlr.v4.runtime.atn.BlockStartState; +import org.antlr.v4.runtime.atn.DecisionState; +import org.antlr.v4.runtime.atn.LL1Analyzer; +import org.antlr.v4.runtime.atn.PrecedencePredicateTransition; +import org.antlr.v4.runtime.atn.PredicateTransition; +import org.antlr.v4.runtime.atn.RuleTransition; +import org.antlr.v4.runtime.atn.Transition; +import org.antlr.v4.runtime.misc.IntervalSet; +import org.antlr.v4.tool.Grammar; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Detects prefix-factorable decisions: block decisions whose + * alternatives partition into groups sharing an identical leading element + * sequence (token matches and rule invocations) that ends at a rule + * invocation, with pairwise LL(1)-disjoint tails. For such a group the + * static prediction walker may accept with an alternative mask + * (the still-live alternatives) instead of a unique alternative or an + * adaptive escape: the generated parser executes the shared prefix once + * and defers the choice to a trivial tail decision ("implied + * left-factoring"). + * + *

The canonical shape is the parenthesized family of an expression + * rule: {@code '(' expression (',' expression)+ ')'} (row constructor) + * vs {@code '(' expression ')'}. Both share {@code '(' expression}; + * after the shared invocation returns, the tails begin with ',' and ')' + * respectively - disjoint, so the tail is decidable with k=1. The + * unbounded expression descent in between is what defeats unique-alt + * static prediction; the mask protocol accepts the decision at the + * shallow depth where the live set narrows to the group.

+ * + *

Soundness: the walker only ever removes alternatives whose SLL + * configurations all died on the scanned prefix, and SLL viability + * over-approximates full-context viability - so the returned mask is + * always a superset of the runtime's live alternatives, and every group + * member genuinely begins with the shared prefix (element-level + * equality proven here).

+ * + *

v1 restrictions: shared prefixes end at a rule invocation and + * contain no predicates/actions; set transitions and sub-blocks end the + * prefix; tails must be non-nullable with pairwise-disjoint local FIRST + * sets; decisions with more than 64 alternatives are excluded (the mask + * is a u64).

+ */ +public class PrefixFactorAnalyzer { + + /** A prefix element: a token match or a rule invocation. */ + public static final class Element { + public static final int TOKEN = 1; + public static final int RULE = 2; + public final int kind; + /** Token type for {@link #TOKEN}, rule index for {@link #RULE}. */ + public final int id; + + public Element(int kind, int id) { this.kind = kind; this.id = id; } + + @Override + public boolean equals(Object o) { + return o instanceof Element && ((Element)o).kind == kind && ((Element)o).id == id; + } + + @Override + public int hashCode() { return kind * 1000003 + id; } + + public String toString(Grammar g) { + if (kind == TOKEN) { + String name = g.getTokenDisplayName(id); + return name != null ? name : String.valueOf(id); + } + return "<" + g.getRule(id).name + ">"; + } + } + + /** One prefix group: alternatives sharing {@link #prefix}, with + * LL(1)-disjoint tails starting at {@link #tailStartState}. */ + public static final class Group { + public final BitSet alts = new BitSet(); + public final List prefix; + /** Per-alternative ATN state where the tail begins (right after + * the shared rule invocation's follow state). */ + public final Map tailStartState = new HashMap(); + /** Per-alternative local tail FIRST (block-end delimited). */ + public final Map tailFirst = new HashMap(); + + public Group(List prefix) { this.prefix = prefix; } + + public String toString(Grammar g) { + StringBuilder sb = new StringBuilder(); + sb.append(alts).append(" prefix="); + for (Element e : prefix) sb.append(e.toString(g)).append(' '); + sb.append("tails="); + for (Map.Entry e : tailFirst.entrySet()) { + sb.append(e.getKey()).append(':') + .append(e.getValue().toString(g.getVocabulary())).append(' '); + } + return sb.toString().trim(); + } + } + + /** The factor plan of one decision: its validated groups. */ + public static final class Plan { + public final int decision; + public final List groups = new ArrayList(); + + public Plan(int decision) { this.decision = decision; } + + public boolean hasGroups() { return !groups.isEmpty(); } + + /** The single group covering the given live-alternative set, or + * null when the live set spans groups or outside alternatives. + * A live set of cardinality < 2 needs no mask (unique-alt + * acceptance handles it). */ + public Group groupCovering(BitSet liveAlts) { + if (liveAlts.cardinality() < 2) return null; + Group found = null; + for (Group g : groups) { + BitSet b = (BitSet)liveAlts.clone(); + b.and(g.alts); + if (b.equals(liveAlts)) { + if (found != null) return null; // covered by two groups: reject + found = g; + } + } + return found; + } + } + + /** Per-alternative extraction result: the leading element sequence, + * the state following each element, and where actions or + * predicates were seen along the way. */ + private static final class AltPath { + final List elements = new ArrayList(); + /** stateAfter[i] = state number after elements[i] (for a RULE + * element, the rule transition's follow state). */ + final List stateAfter = new ArrayList(); + /** Element depth of the first action seen (elements.size() at + * that point); actions at depth >= a group's shared prefix + * length are inside tails and benign. Integer.MAX_VALUE = none. */ + int firstActionDepth = Integer.MAX_VALUE; + /** Any predicate seen anywhere on the path (tails included: + * the tail-FIRST proof cannot see through predicates). */ + boolean sawPredicate; + } + + private final Grammar g; + private final ATN atn; + private final LL1Analyzer ll1; + + public PrefixFactorAnalyzer(Grammar g, ATN atn) { + this.g = g; + this.atn = atn; + this.ll1 = new LL1Analyzer(atn); + } + + /** Analyze a decision; returns a plan (possibly without groups). + * Never returns null. */ + public Plan analyze(DecisionState ds) { + Plan plan = new Plan(ds.decision); + if (!(ds instanceof BlockStartState)) return plan; + int nAlts = ds.getNumberOfTransitions(); + if (nAlts < 2 || nAlts > 64) return plan; + + BlockStartState block = (BlockStartState)ds; + List paths = new ArrayList(); + boolean dbg = "factor".equals(System.getProperty("antlr.dfa.debug")); + for (int i = 0; i < nAlts; i++) { + AltPath p = extract(ds.transition(i).target); + paths.add(p); + if (dbg) { + StringBuilder sb = new StringBuilder(); + sb.append(" EXTRACT d=").append(ds.decision).append(" alt=").append(i+1).append(":"); + for (Element e : p.elements) sb.append(' ').append(e.toString(g)); + sb.append(" (actionDepth=").append(p.firstActionDepth) + .append(" sawPred=").append(p.sawPredicate).append(')'); + System.err.println(sb); + } + } + + // Candidate groups: maximal clusters of alternatives sharing a + // prefix of length >= 2 that ends at a rule invocation. Computed + // by descending shared-prefix length; an alternative joins at + // most one group (the one at its deepest shared node). + BitSet grouped = new BitSet(); + int maxLen = 0; + for (AltPath p : paths) maxLen = Math.max(maxLen, p.elements.size()); + for (int len = maxLen; len >= 2; len--) { + Map, List> byKey = new HashMap, List>(); + for (int alt = 1; alt <= nAlts; alt++) { + if (grouped.get(alt)) continue; + AltPath p = paths.get(alt-1); + if (p.elements.size() < len) continue; + if (p.elements.get(len-1).kind != Element.RULE) continue; + List key = new ArrayList(p.elements.subList(0, len)); + byKey.computeIfAbsent(key, k -> new ArrayList()).add(alt); + } + for (List members : byKey.values()) { + if (members.size() < 2) continue; + Group grp = buildGroup(paths, members, len, block); + if (grp != null) { + plan.groups.add(grp); + for (int alt : members) grouped.set(alt); + } + } + } + return plan; + } + + /** Validate a candidate group and populate it; null when invalid. */ + private Group buildGroup(List paths, List members, int len, + BlockStartState block) { + AltPath first = paths.get(members.get(0)-1); + // No actions inside the shared region; no predicates anywhere + // (the tail-FIRST proof cannot see through them). + for (int alt : members) { + AltPath p = paths.get(alt-1); + if (p.firstActionDepth < len || p.sawPredicate) return null; + } + Group grp = new Group(new ArrayList(first.elements.subList(0, len))); + for (int alt : members) { + AltPath p = paths.get(alt-1); + grp.alts.set(alt); + grp.tailStartState.put(alt, p.stateAfter.get(len-1)); + } + // Tails: local FIRST delimited by the decision's block end; must + // be non-nullable, non-empty, and pairwise disjoint. + IntervalSet union = new IntervalSet(); + for (int alt : members) { + ATNState tailStart = atn.states.get(grp.tailStartState.get(alt)); + IntervalSet f = ll1.LOOK(tailStart, block.endState, null); + if (f.isNil() || f.contains(Token.EPSILON)) return null; + grp.tailFirst.put(alt, f); + if (union.and(f).size() > 0) return null; + union.addAll(f); + } + return grp; + } + + /** Extract the leading element sequence of one alternative: walk + * from its first state, recording token matches and rule + * invocations, following single-epsilon links, and stopping at any + * fanout (sub-block), set transition, loop back-edge, or mixed + * state. */ + private AltPath extract(ATNState start) { + AltPath path = new AltPath(); + Set visited = new HashSet(); + ATNState cur = start; + while (cur != null && visited.add(cur.stateNumber)) { + int n = cur.getNumberOfTransitions(); + if (n == 0) break; + if (n == 1) { + Transition t = cur.transition(0); + if (t instanceof ActionTransition) { + path.firstActionDepth = Math.min(path.firstActionDepth, path.elements.size()); + cur = t.target; + continue; + } + if (t instanceof PredicateTransition + || t instanceof PrecedencePredicateTransition) { + path.sawPredicate = true; + cur = t.target; + continue; + } + // NB: RuleTransition.isEpsilon() is true - it must be + // handled before the generic epsilon follow. + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + path.elements.add(new Element(Element.RULE, rt.ruleIndex)); + path.stateAfter.add(rt.followState.stateNumber); + cur = rt.followState; + continue; + } + if (t.isEpsilon()) { cur = t.target; continue; } + if (t instanceof org.antlr.v4.runtime.atn.AtomTransition) { + path.elements.add(new Element(Element.TOKEN, + ((org.antlr.v4.runtime.atn.AtomTransition)t).label)); + path.stateAfter.add(t.target.stateNumber); + cur = t.target; + continue; + } + break; // set/wildcard transition: prefix ends + } + // Fanout: v1 stops the prefix here. Still note predicates + // (they end prefix extraction but poison the tail proof if + // they fall inside a would-be tail). + for (int i = 0; i < n; i++) { + Transition t = cur.transition(i); + if (t instanceof ActionTransition) { + path.firstActionDepth = Math.min(path.firstActionDepth, path.elements.size()); + } + if (t instanceof PredicateTransition + || t instanceof PrecedencePredicateTransition) { + path.sawPredicate = true; + } + } + break; + } + return path; + } +} From 6ca35785af1e6ebef6dbd000e11a88b903724909 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 18 Jul 2026 20:32:21 -0400 Subject: [PATCH 16/48] Static DFA table format v6: alternative-mask accepts + mask-capable walkers Tables may now mark a state as mask-accept: its live alternatives are covered by one prefix-factor group, so the walker returns the group's alternative bitmask instead of a unique alt or an escape. Mask accepts are emitted only where a state would otherwise escape (conflict or budget frontier), so this strictly enlarges what tables resolve; Trino d=316 goes from 89 escapes to 71 escapes + 18 mask accepts. Wire format: v6 appends a per-table mask section (state, alts...) after each table's edges; decoders reconstruct per-state bitmasks. Runtime protocol: dfa_predict_mask(decision) -> u64 (bit 1<<(alt-1) per live alt; 0 = defer to adaptive) shares the walker core with dfa_predict, which degrades mask states to adaptive deferral for call sites without a factored alternative path. The Java runtime (no factored codegen) likewise defers mask states and traces them as 'mask-defer'. Verified: the Rust walker returns mask {2,25} (0x1000002) at Trino d=316's hot state 226 on 'WHERE COL = (1 + 2)'; Java defers the same state and parses identically; cargo test green; ExprLoops differential 1690/1690 identical. Factored codegen (mask arms in generated parsers) is M2. Signed-off-by: Bo Lin --- .../Java/src/org/antlr/v4/runtime/Parser.java | 13 ++-- .../antlr/v4/runtime/atn/StaticDFATables.java | 22 +++++- runtime/Rust/src/parser.rs | 55 +++++++++++++-- runtime/Rust/src/static_dfa.rs | 44 +++++++++++- runtime/Rust/tests/gen/betweenexprparser.rs | 16 ++--- runtime/Rust/tests/gen/fuzzexprparser.rs | 20 +++--- runtime/Rust/tests/gen/lrdfaparser.rs | 12 ++-- runtime/Rust/tests/gen/staticdfaparser.rs | 8 +-- .../antlr/v4/analysis/DecisionClassifier.java | 68 ++++++++++++------- tool/src/org/antlr/v4/analysis/StaticDFA.java | 15 +++- .../codegen/model/SerializedStaticDFAs.java | 33 ++++++++- 11 files changed, 237 insertions(+), 69 deletions(-) diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java index c17e45f871..19ddff8a58 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java @@ -566,12 +566,15 @@ public int dfaPredict(StaticDFATables tables, int decision) while (true) { int alt = tables.accept(table, s); if ( alt>0 ) return alt; - if ( alt==StaticDFATables.ESCAPE ) { - // hybrid-table escape: rerun the prediction through the - // adaptive engine (no input was consumed, so the rescan - // starts clean) + if ( alt<0 ) { + // hybrid-table escape (-1) or mask-accept state (-2; Java + // has no factored codegen): rerun the prediction through + // the adaptive engine (no input was consumed, so the + // rescan starts clean) if ( System.getProperty("antlr.dfa.trace") != null ) { - System.err.println("DFA-TRACE escape d="+decision+" prec="+getPrecedence()+" state="+s+" la1="+_input.LA(1)); + System.err.println("DFA-TRACE " + +(alt==StaticDFATables.MASK_DEFER ? "mask-defer" : "escape") + +" d="+decision+" prec="+getPrecedence()+" state="+s+" la1="+_input.LA(1)); } return getInterpreter().adaptivePredict(_input, decision, _ctx); } diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java index 835d044770..47bac1bf22 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java @@ -60,7 +60,7 @@ */ public class StaticDFATables { /** Must match the tool's SerializedStaticDFAs.FORMAT_VERSION. */ - public static final int FORMAT_VERSION = 5; + public static final int FORMAT_VERSION = 6; /** Concatenated per-table data: accepts, fallbacks, edgeOffsets, edges. */ protected final int[] data; @@ -124,6 +124,19 @@ public static StaticDFATables deserialize(String[] segments) { for (int i = 0; i < numStates+1; i++) data.add(ints.next()); metas[table*5+3] = data.size; // edgesAt for (int i = 0; i < numEdgeInts; i++) data.add(ints.next()); + // v6: alternative-mask section. The Java target has no + // factored codegen, so a mask-accept state simply defers to + // adaptivePredict - exactly like an escape state - and the + // mask's member alternatives are not retained here (the Rust + // runtime, which does implement the mask protocol, decodes + // them from the same section). + int numMaskStates = ints.next(); + for (int i = 0; i < numMaskStates; i++) { + int state = ints.next(); + int numAlts = ints.next(); + for (int a = 0; a < numAlts; a++) ints.next(); + data.set(metas[table*5]+state, MASK_DEFER); + } metas[table*5+4] = data.size; // endAt } int numDispatches = ints.next(); @@ -144,6 +157,11 @@ public static StaticDFATables deserialize(String[] segments) { /** {@code accepts} sentinel: a hybrid table's escape state - the walker * defers the whole prediction to {@code adaptivePredict}. */ public static final int ESCAPE = -1; + /** {@code accepts} sentinel: a mask-accept state (the live alternatives + * are covered by one prefix-factor group). Java has no factored + * codegen, so the walker defers to {@code adaptivePredict}; the Rust + * runtime resolves the mask through its factored alternative path. */ + public static final int MASK_DEFER = -2; /** * Is {@code decision} precedence-dispatched (per-precedence-class @@ -248,6 +266,8 @@ void add(int v) { data[size++] = v; } + void set(int i, int v) { data[i] = v; } + int[] toArray() { int[] result = new int[size]; System.arraycopy(data, 0, result, 0, size); diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 2b8e14f351..c6e35a6ece 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -494,6 +494,35 @@ where } pub fn dfa_predict(&mut self, decision: i32) -> Result { + let mask = self.dfa_walk(decision)?; + if mask == 0 || !mask.is_power_of_two() { + // defer to the adaptive engine: escape state, no table, or a + // mask-accept state this call site has no factored + // alternative path for + Ok(crate::atn::INVALID_ALT) + } else { + Ok(mask.trailing_zeros() as i32 + 1) + } + } + + /// Mask-returning sibling of [`Self::dfa_predict`]: walks the same + /// static table but returns the set of live alternatives as a bitmask + /// (bit `1<<(alt-1)` per alternative) instead of a unique + /// alternative. A mask-accept state returns its mask: the live + /// alternatives are covered by one prefix-factor group, so the + /// generated parser executes the group's shared prefix and resolves + /// the choice with its tail decision. `0` defers to the adaptive + /// engine (same conditions as `dfa_predict` returning + /// [`crate::atn::INVALID_ALT`]); a unique accept returns its + /// single-bit mask. + pub fn dfa_predict_mask(&mut self, decision: i32) -> Result { + self.dfa_walk(decision) + } + + /// The shared static-table walk: the prediction of `decision` as an + /// alternative mask, or `0` when the table defers to the adaptive + /// engine. + fn dfa_walk(&mut self, decision: i32) -> Result { // the precedence selects the table of dispatched decisions (the // operator loops of left-recursive rules); plain decisions ignore it let precedence = self.get_precedence(); @@ -504,14 +533,14 @@ where // rule's compatible call sites, but an entry invocation pops // into the grammar-wide FOLLOW space instead - only the // adaptive engine models that. - return Ok(crate::atn::INVALID_ALT); + return Ok(0); } let Some(dfa) = static_dfas.table(decision, precedence) else { // this precedence class has no static table if Self::dfa_trace() { eprintln!("DFA-TRACE no-table d={} prec={}", decision, precedence); } - return Ok(crate::atn::INVALID_ALT); + return Ok(0); }; let mut s = 0usize; let mut i = 1isize; @@ -530,10 +559,26 @@ where self.input.la(1) ); } - return Ok(crate::atn::INVALID_ALT); + return Ok(0); + } + if let Some(mask) = dfa.accept_mask(s) { + // mask-accept: the live alternatives are covered by one + // prefix-factor group + if Self::dfa_trace() { + eprintln!( + "DFA-TRACE mask d={} prec={} state={} depth={} la1={} mask={:#x}", + decision, + precedence, + s, + i - 1, + self.input.la(1), + mask + ); + } + return Ok(mask); } if let Some(alt) = dfa.accept(s) { - return Ok(alt); + return Ok(1u64 << (alt - 1)); } let t = self.input.la(i); match dfa.edge(s, t) { @@ -548,7 +593,7 @@ where // mismatch point - mirroring adaptive_predict's // finished-decision-entry-rule recovery. if let Some(alt) = dfa.fallback(s) { - return Ok(alt); + return Ok(1u64 << (alt - 1)); } let start = self.input.lt(1).map(|t| OwningToken::from(t as &dyn Token)); let offending = self.input.lt(i).map(|t| OwningToken::from(t as &dyn Token)); diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs index 6da8a93710..2c42bda4a0 100644 --- a/runtime/Rust/src/static_dfa.rs +++ b/runtime/Rust/src/static_dfa.rs @@ -47,8 +47,9 @@ //! behaves like a hand-rolled precedence-climbing (Pratt) parser. /// Format version understood by this runtime; must match the tool's -/// `SerializedStaticDFAs.FORMAT_VERSION`. -pub const FORMAT_VERSION: i32 = 5; +/// `SerializedStaticDFAs.FORMAT_VERSION`. v6 adds the per-table +/// alternative-mask section (prefix-factor groups). +pub const FORMAT_VERSION: i32 = 6; /// The deserialized static prediction tables of one generated parser. /// @@ -67,6 +68,9 @@ pub struct StaticDFATables { data: Vec, /// Per-table (accepts_at, fallbacks_at, edge_offsets_at, edges_at) indexes into `data`. metas: Vec<(usize, usize, usize, usize)>, + /// Per-table alternative-mask accepts (bit 1<<(alt-1) per live + /// alternative of the covering prefix-factor group; 0 = none). + masks: Vec>, /// decision number -> table index (`>= 0`), `-1` (no table), or /// `-(dispatch index) - 2` (precedence-dispatched decision). decision_to_table: Vec, @@ -82,6 +86,12 @@ pub struct StaticDFATables { pub struct StaticDFATable<'a> { /// Predicted alternative per state; 0 = not an accept state. pub accepts: &'a [i32], + /// Alternative-mask accept per state; 0 = none. A nonzero entry marks + /// a terminal state where the walker returns the mask: the live + /// alternatives are covered by one prefix-factor group, so the + /// generated parser executes the group's shared prefix and resolves + /// the choice with its tail decision. + pub masks: &'a [u64], /// Error-avoidance fallback per state; 0 = none. Returned when a /// lookahead token matches no edge, so the parser fails later with a /// more precise error at the mismatch point - mirroring @@ -101,6 +111,7 @@ impl StaticDFATables { Self { data: Vec::new(), metas: Vec::new(), + masks: Vec::new(), decision_to_table: Vec::new(), dispatch_data: Vec::new(), dispatch_at: Vec::new(), @@ -129,6 +140,7 @@ impl StaticDFATables { let mut data = Vec::new(); let mut metas = Vec::with_capacity(num_tables); + let mut masks = Vec::with_capacity(num_tables); let mut decision_to_table = vec![-1i32; num_slots]; for table in 0..num_tables { @@ -155,6 +167,19 @@ impl StaticDFATables { for _ in 0..num_edge_ints { data.push(next()); } + // v6: alternative-mask section + let num_mask_states = next() as usize; + let mut table_masks = vec![0u64; num_states]; + for _ in 0..num_mask_states { + let state = next() as usize; + let num_alts = next() as usize; + let mut bits = 0u64; + for _ in 0..num_alts { + bits |= 1u64 << (next() - 1); + } + table_masks[state] = bits; + } + masks.push(table_masks); metas.push((accepts_at, fallbacks_at, edge_offsets_at, edges_at)); } @@ -177,6 +202,7 @@ impl StaticDFATables { Self { data, metas, + masks, decision_to_table, dispatch_data, dispatch_at, @@ -225,6 +251,7 @@ impl StaticDFATables { .unwrap_or(self.data.len()); Some(StaticDFATable { accepts: &self.data[accepts_at..fallbacks_at], + masks: &self.masks[t as usize], fallbacks: &self.data[fallbacks_at..edge_offsets_at], edge_offsets: &self.data[edge_offsets_at..edges_at], edges: &self.data[edges_at..end], @@ -256,6 +283,19 @@ impl<'a> StaticDFATable<'a> { self.accepts[state] == ESCAPE } + /// Alternative mask of `state` when it mask-accepts (the live + /// alternatives are covered by one prefix-factor group; bit + /// `1<<(alt-1)` per member). + #[inline] + pub fn accept_mask(&self, state: usize) -> Option { + let m = self.masks[state]; + if m != 0 { + Some(m) + } else { + None + } + } + /// Error-avoidance fallback alternative of `state`, if any. #[inline] pub fn fallback(&self, state: usize) -> Option { diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index ace01529bc..8b7cd0dd8a 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -1697,12 +1697,12 @@ static _serializedATN: [&'static str; 19] = [ "FAYAAGJkDgIAAGRuBgwGCGZoFAQAAGhqDgQAAGpuBgwGBmxgAgAAAGxmAgAAAG50AgAAAHBsAgAAAHBy", "AgAAAHIOAgAAAHRwAgAAAHaKAQoeAAB4igEKIAAAenwKGAAAfH4GBAIAfoABChoAAIABigECAAAAggGE", "AQoeAACEAYYBChwAAIYBigEGBAIAiAF2AgAAAIgBeAIAAACIAXoCAAAAiAGCAQIAAACKARICAAAAEiAo", - "ODxEVmxwiAEKEhIAEjAABAEEBAEBBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", - "EBYOGhoQBAYMAAIEAAAAAAwMDAQEAgYGBAwGDAACBAAAAAAMDAwQEgIUFgQQGkgABgAEAgICAgICAgII", - "AAACAAAAAAAAAAAAAAASEkhISEhISEhISEhIGBgCHh4EICAGAQEIAgIKBAQMBgYOCAgQCg4SEBYUGhoW", - "HBwYARIwAAQEAQIEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAES", - "MAAEBAEEBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4aGhABAgAEAAAA", - "ARIwAAQEBAQEBAIEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAEUNgAE", - "BAQEBAQCBAQEAAAAAAAAAAAAADY2NjY2NjY2NjYBAQICAgQEBAYGBggICAoKDgwQEg4UFhAaGhIEBgQC", - "BAgKDA4EBAYOEAw=" + "ODxEVmxwiAEMEhIAEjAABAEEBAEBBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", + "EBYOGhoQAAQGDAACBAAAAAAMDAwEBAIGBgQADAYMAAIEAAAAAAwMDBASAhQWBAAQGkgABgAEAgICAgIC", + "AgIIAAACAAAAAAAAAAAAAAASEkhISEhISEhISEhIGBgCHh4EICAGAQEIAgIKBAQMBgYOCAgQCg4SEBYU", + "GhoWHBwYAAESMAAEBAECBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4a", + "GhAAARIwAAQEAQQEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAAB", + "AgAEAAAAAAESMAAEBAQEBAQCBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4a", + "GhAAARQ2AAQEBAQEBAIEBAQAAAAAAAAAAAAANjY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBASDhQW", + "EBoaEgAEBgQCBAgKDA4EBAYOEAw=" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index ca2ec64295..e0513cf863 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -1215,19 +1215,19 @@ static _serializedATN: [&'static str; 29] = [ "hgGuAQYMBgCIAa4BCh4AAIoBjAEKGAAAjAGOAQYQCACOAZABChoAAJABrgECAAAAkgGUAQocAACUAaYB", "ChgAAJYBoAEGEAgAmAGaAQoCAACaAZ4BBhAIAJwBmAECAAAAngGkAQIAAACgAZwBAgAAAKABogECAAAA", "ogGoAQIAAACkAaABAgAAAKYBlgECAAAApgGoAQIAAACoAaoBAgAAAKoBrgEKGgAArAGGAQIAAACsAYgB", - "AgAAAKwBigECAAAArAGSAQIAAACuARYCAAAAFCIqPE5cfIABoAGmAawBChIUBEDOAwAAAQEAAAQEBAIA", + "AgAAAKwBigECAAAArAGSAQIAAACuARYCAAAAFCIqPE5cfIABoAGmAawBDBIUBEDOAwAAAQEAAAQEBAIA", "AAABAAEBAAAAAQEAAAEBAQEBAQEBAAQAAAQEAAAAAAAAAAAAAAAAAAQAAAQEAAAAAAAAAAAAHkhISHic", "AZwBnAGcAZwBqAHGAeQB5AH8AfwB/AGaAqwC4gLiAuICngPOA84DzgPOA84DzgPOA84DzgMGBgIODgQY", "GAYcHAgeHgoBAQwCAg4EBBAGBhIICBQKChYOFhgBAQwCAg4EBBAGBhIICBQKChYOFhgYGBoBAQwCAg4E", "BBAGBhIKChYOFhgGBgIcHAIGBhwODh4YGCAcHCIeHiQGBiYODigYGCocHCweHi4ICDAKCjIMDAoOFjQI", "CDAKCjIMDAoOFjQYGDYKCjIMDAoOFjQBAQwCAg4EBBAGBhIICDgKCjoODhgQFDwWFhgBAQwCAg4EBBAG", - "BhIICDgKCjoODhgQFDwWFhgYGD4BAQwCAg4EBBAGBhIKCjoODhgQFDwWFhgGFDYABAQEBAIEBAQEBAAA", - "AAAAAAAAAAA2NjY2NjY2NjY2AQECAgIEBAQGBgYICAgKCgoMDAwODhYQGhoSCgoeAAgGAgQAAAAAAAAe", - "Hh4eHgoKAg4OBBAQBhIUCBYWBBIeVAACBgAEAgICAgICAgIIAgAAAAIAAAAAAAAAAAAAAAAYGBhUVFRU", - "VFRUVFRUVFQGBgIYGAQcHAYeHggBAQoCAgwEBA4GBhAICBIKChQMDBYOFhgYGBoaGhwBEjAABAQEBAIE", - "AgQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICgoKDAwMDhYOGhoQARQ8AAQEBAQCBAQCBAQA", - "AAAAAAAAAAAAPDw8PDw8PDw8PAEBAgICBAQEBgYGCAoKCgwMDA4ODhAUEBYWDhoaEgEUPAAEBAQEAgQE", - "AgQEAAAAAAAAAAAAADw8PDw8PDw8PDwBAQICAgQEBAYGBggKCgoMDAwODg4QEBASFg4aGhIBEjAABAQE", - "BAIEBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICgoKDAwMDhYOGhoQAQIABAAAAAIMCAQG", - "CAwICgwOEA==" + "BhIICDgKCjoODhgQFDwWFhgYGD4BAQwCAg4EBBAGBhIKCjoODhgQFDwWFhgABhQ2AAQEBAQCBAQEBAQA", + "AAAAAAAAAAAANjY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoKDAwMDg4WEBoaEgAKCh4ACAYCBAAAAAAA", + "AB4eHh4eCgoCDg4EEBAGEhQIFhYEABIeVAACBgAEAgICAgICAgIIAgAAAAIAAAAAAAAAAAAAAAAYGBhU", + "VFRUVFRUVFRUVFQGBgIYGAQcHAYeHggBAQoCAgwEBA4GBhAICBIKChQMDBYOFhgYGBoaGhwAARIwAAQE", + "BAQCBAIEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAoKCgwMDA4WDhoaEAABFDwABAQEBAIE", + "BAIEBAAAAAAAAAAAAAA8PDw8PDw8PDw8AQECAgIEBAQGBgYICgoKDAwMDg4OEBQQFhYOGhoSAAEUPAAE", + "BAQEAgQEAgQEAAAAAAAAAAAAADw8PDw8PDw8PDwBAQICAgQEBAYGBggKCgoMDAwODg4QEBASFg4aGhIA", + "ARIwAAQEBAQCBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAoKCgwMDA4WDhoaEAABAgAE", + "AAAAAAIMCAQGCAwICgwOEA==" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/lrdfaparser.rs b/runtime/Rust/tests/gen/lrdfaparser.rs index 37cfddf3a2..6c8132aad4 100644 --- a/runtime/Rust/tests/gen/lrdfaparser.rs +++ b/runtime/Rust/tests/gen/lrdfaparser.rs @@ -1525,10 +1525,10 @@ static _serializedATN: [&'static str; 12] = [ "AAAYFgIAAAAaTAIAAAAcHhQMAAAeIAoKAAAgSgYEAgwiJBQKAAAkJg4AAAAmSgYEAgwoKhQIAAAqLA4C", "AAAsSgYEAgouMBQGAAAwMgoSAAAyNAYEAgA0NgoUAAA2OAYEAgY4SgIAAAA6PBQSAAA8PgoCAAA+QAYE", "AgBAQgoEAABCSgIAAABERhQQAABGSgoGAABIHAIAAABIIgIAAABIKAIAAABILgIAAABIOgIAAABIRAIA", - "AABKUAIAAABMSAIAAABMTgIAAABOBgIAAABQTAIAAAAGGEhMChAGAg4qAAoMBgIECAAAAAAAAAAAKioq", - "KioqKgICAgYGBAgIBgoKCAwOChAQBhISDAEQKgAEAgQCAgIEBAAAAAAAAAAAKioqKioqKioBAQICAgQE", - "BAYGBggIEAoSEgwUFA4BChgABAICAgQAAAAAABgYGBgYAQECAgIEBgYGCBAIARI2AAQCBAIEAgQEBAAA", - "AAAAAAAAADY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBAQChISDhQUEAEKGAAEAgICBAAAAAAAGBgY", - "GBgBAQICAgQGBgYKCggBECoABAIEAgQEBAQAAAAAAAAAACoqKioqKioqAQECAgIEBAQGBgYICBAKEhIM", - "FBQOAQYMAAQCBAAAAAwMDAEBAgICBAECAAQAAAACBAwGCAoMEBICBAYICgwO" + "AABKUAIAAABMSAIAAABMTgIAAABOBgIAAABQTAIAAAAGGEhMDBAGAg4qAAoMBgIECAAAAAAAAAAAKioq", + "KioqKgICAgYGBAgIBgoKCAwOChAQBhISDAABECoABAIEAgICBAQAAAAAAAAAACoqKioqKioqAQECAgIE", + "BAQGBgYICBAKEhIMFBQOAAEKGAAEAgICBAAAAAAAGBgYGBgBAQICAgQGBgYIEAgAARI2AAQCBAIEAgQE", + "BAAAAAAAAAAAADY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBAQChISDhQUEAABChgABAICAgQAAAAA", + "ABgYGBgYAQECAgIEBgYGCgoIAAEQKgAEAgQCBAQEBAAAAAAAAAAAKioqKioqKioBAQICAgQEBAYGBggI", + "EAoSEgwUFA4AAQYMAAQCBAAAAAwMDAEBAgICBAABAgAEAAAAAAIEDAYICgwQEgIEBggKDA4=" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index 4f51444836..dbfe7adf7d 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -1827,8 +1827,8 @@ static _serializedATN: [&'static str; 14] = [ "AAAAWFQCAAAAWFoCAAAAWl4CAAAAXFgCAAAAXmAKEAAAYGIKFAAAYg4CAAAAZGYKEAAAZmoKEgAAaGQC", "AAAAamwCAAAAbGgCAAAAbG4CAAAAbnACAAAAcHIKEAAAcnQKFAAAdBICAAAAdngKEAAAeHwKEgAAenYC", "AAAAenwCAAAAfH4CAAAAfoABChAAAIABggEKFAAAggEWAgAAAIQBhgEKFgAAhgGOAQoYAACIAYoBChYA", - "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEKDA4AChgAAAYCBAAAAAAAAAwY", - "GBgYAgICCAgEBAQGBgYIAgoeAAAEAgAABAAAAAAGGBgYHhoaAgEBBAoKBg4OCBoaAgYIEgAAAgQAAAAA", - "AAYSEhIQEAISEgQUFAYICBIAAAIEAAAAAAAGEhISEBACEhIEFBQGCggSAAACBAAAAAAABhISEhAQAhIS", - "BBQUBgwGDAAAAgAAAAAGDAwWFgIYGAQA" + "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEMDA4AChgAAAYCBAAAAAAAAAwY", + "GBgYAgICCAgEBAQGBgYIAAIKHgAABAIAAAQAAAAABhgYGB4aGgIBAQQKCgYODggaGgIABggSAAACBAAA", + "AAAABhISEhAQAhISBBQUBgAICBIAAAIEAAAAAAAGEhISEBACEhIEFBQGAAoIEgAAAgQAAAAAAAYSEhIQ", + "EAISEgQUFAYADAYMAAACAAAAAAYMDBYWAhgYBAAA" ]; \ No newline at end of file diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 3069d4c23d..f5d9b9beac 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -973,6 +973,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List> edges = new ArrayList>(); List> edgeLabels = new ArrayList>(); List acceptAlts = new ArrayList(); // 0 = not an accept state + List acceptMasks = new ArrayList(); // 0 = not a mask-accept state List fallbackAlts = new ArrayList(); // 0 = none List stateDepth = new ArrayList(); // lookahead depth (BFS layer) @@ -1002,6 +1003,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { edges.add(new ArrayList()); edgeLabels.add(new ArrayList()); acceptAlts.add(0); + acceptMasks.add(0L); fallbackAlts.add(0); stateDepth.add(0); @@ -1023,21 +1025,14 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { continue; } - // alt-mask dry run: a state whose live alternatives fall - // inside a single prefix-factor group would accept with an - // alternative mask instead of resolving further (or escaping) + // alt-mask acceptance: a state whose live alternatives fall + // inside a single prefix-factor group resolves to an + // alternative mask instead of a unique alt or an escape; the + // generated parser executes the group's shared prefix and + // defers the choice to its tail decision PrefixFactorAnalyzer.Group factorGroup = currentFactorPlan != null ? currentFactorPlan.groupCovering(alts) : null; - if (factorGroup != null) { - res.factorMaskStates++; - if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { - // terminal simulation: measure the mask-protocol - // table - a mask accept ends the walk, so the whole - // subtree below is never built (and never escapes) - acceptAlts.set(d, Math.max(0, alts.nextSetBit(0))); - continue; - } - } + if (factorGroup != null) res.factorMaskStates++; if (PredictionMode.hasSLLConflictTerminatingPrediction(PredictionMode.SLL, cs)) { Collection altSubsets = PredictionMode.getConflictingAltSubsets(cs); boolean exact = PredictionMode.allSubsetsConflict(altSubsets) @@ -1179,15 +1174,22 @@ && hasPendingPrecReturn(c.context)) { } else if (hybridMode) { // the conflict cannot be resolved statically: defer - // this state to adaptivePredict + // this state to adaptivePredict - UNLESS its live + // alternatives are covered by one prefix-factor + // group, in which case it accepts with the group's + // alternative mask (the parser resolves the choice + // at the group's tail decision) if (factorGroup != null) { res.factorEscapesCured++; + acceptMasks.set(d, altBits(factorGroup.alts)); if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { - System.err.printf("FACTOR-CURE d=%d state=%d depth=%d alts=%s%n", + System.err.printf("FACTOR-MASK d=%d state=%d depth=%d alts=%s%n", s.decision, d, stateDepth.get(d), alts); } } - acceptAlts.set(d, StaticDFA.ESCAPE); + else { + acceptAlts.set(d, StaticDFA.ESCAPE); + } if (System.getProperty("antlr.dfa.debug") != null) { System.err.printf("ESCAPE-CONFLICT d=%d state=%d depth=%d exact=%s hard=%s anyB=%s allB=%s trustEA=%s alts=%s%n", s.decision, d, stateDepth.get(d), exact, widenedTainted, @@ -1224,12 +1226,15 @@ else if (abortOnUntrustedConflict) { // dynamic majority - escape on sheer decision fanout. if (factorGroup != null) { res.factorEscapesCured++; + acceptMasks.set(d, altBits(factorGroup.alts)); if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { - System.err.printf("FACTOR-CURE-CAP d=%d state=%d depth=%d alts=%s%n", + System.err.printf("FACTOR-MASK-CAP d=%d state=%d depth=%d alts=%s%n", s.decision, d, stateDepth.get(d), alts); } } - acceptAlts.set(d, StaticDFA.ESCAPE); + else { + acceptAlts.set(d, StaticDFA.ESCAPE); + } continue; } @@ -1260,6 +1265,7 @@ else if (abortOnUntrustedConflict) { edges.add(new ArrayList()); edgeLabels.add(new ArrayList()); acceptAlts.add(0); + acceptMasks.add(0L); fallbackAlts.add(0); stateDepth.add(stateDepth.get(d)+1); work.add(id); @@ -1301,9 +1307,9 @@ else if (abortOnUntrustedConflict) { // something - a start-state escape means nothing is decidable res.category = Category.HYBRID; res.escapes = escapes; - res.coverage = startCoverage(edges, edgeLabels, acceptAlts); + res.coverage = startCoverage(edges, edgeLabels, acceptAlts, acceptMasks); if (acceptAlts.get(0) != StaticDFA.ESCAPE && res.coverage >= hybridMinCoverage) { - res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, fallbackAlts, cyclic, res.k); + res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, acceptMasks, fallbackAlts, cyclic, res.k); } return false; } @@ -1317,7 +1323,7 @@ else if (abortOnUntrustedConflict) { if (res.category == Category.LLK || res.category == Category.LLSTAR || res.category == Category.EXACT_AMBIG) { - res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, fallbackAlts, cyclic, res.k); + res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, acceptMasks, fallbackAlts, cyclic, res.k); } return false; } @@ -1333,7 +1339,8 @@ else if (abortOnUntrustedConflict) { */ protected static double startCoverage(List> edges, List> edgeLabels, - List acceptAlts) { + List acceptAlts, + List acceptMasks) { int n = edges.size(); // reverse reachability from accept states List> reverse = new ArrayList>(n); @@ -1344,7 +1351,7 @@ protected static double startCoverage(List> edges, boolean[] reachesAccept = new boolean[n]; Deque work = new ArrayDeque(); for (int i = 0; i < n; i++) { - if (acceptAlts.get(i) > 0) { + if (acceptAlts.get(i) > 0 || acceptMasks.get(i) != 0) { reachesAccept[i] = true; work.add(i); } @@ -1405,20 +1412,33 @@ private void dumpOverflowStats(DecisionState s, List> states, int System.err.println(sb); } + /** Alternative-set bitmask of a prefix-factor group (bit 1<<(alt-1) + * per member alternative). */ + protected static long altBits(BitSet alts) { + long bits = 0; + for (int a = alts.nextSetBit(0); a >= 0; a = alts.nextSetBit(a+1)) { + bits |= 1L << (a-1); + } + return bits; + } + /** Serialize the recorded DFA into the flat table form used by codegen. */ protected static StaticDFA toStaticDFA(int decision, List> edgeLabels, List> edgeTargets, List acceptAlts, + List acceptMasks, List fallbackAlts, boolean cyclic, int maxK) { int n = edgeTargets.size(); int[] accepts = new int[n]; + long[] masks = new long[n]; int[] fallbacks = new int[n]; int[] offsets = new int[n+1]; List triples = new ArrayList(); for (int s = 0; s < n; s++) { accepts[s] = acceptAlts.get(s); + masks[s] = acceptMasks.get(s); fallbacks[s] = fallbackAlts.get(s); offsets[s] = triples.size()*3; List stateTriples = new ArrayList(); @@ -1439,7 +1459,7 @@ protected static StaticDFA toStaticDFA(int decision, edges[i*3+1] = triples.get(i)[1]; edges[i*3+2] = triples.get(i)[2]; } - return new StaticDFA(decision, n, accepts, fallbacks, offsets, edges, cyclic, maxK); + return new StaticDFA(decision, n, accepts, masks, fallbacks, offsets, edges, cyclic, maxK); } /** A DFA edge under construction: token class label -> successor config set. */ diff --git a/tool/src/org/antlr/v4/analysis/StaticDFA.java b/tool/src/org/antlr/v4/analysis/StaticDFA.java index 72811adaa4..a00dbd90ed 100644 --- a/tool/src/org/antlr/v4/analysis/StaticDFA.java +++ b/tool/src/org/antlr/v4/analysis/StaticDFA.java @@ -48,6 +48,16 @@ public boolean hasEscapes() { public final int numStates; /** Predicted alternative per state; 0 = not an accept state; {@link #ESCAPE} = escape. */ public final int[] accepts; + /** + * Alternative-mask accept per state; 0 = none. A nonzero entry marks a + * terminal state where the walker returns the mask (bit {@code 1<<(alt-1)} + * per live alternative) instead of a unique alternative: the live set is + * covered by a single prefix-factor group (see PrefixFactorAnalyzer), so + * the generated parser executes the group's shared prefix and resolves + * the choice with its tail decision. Only ever set on states that would + * otherwise be escape states. + */ + public final long[] acceptMasks; /** * Error-avoidance fallback per state; 0 = none. When prediction dies at * a state on a token matching no edge, the walker returns this @@ -66,11 +76,12 @@ public boolean hasEscapes() { /** Max lookahead depth if acyclic; -1 if cyclic. */ public final int maxK; - public StaticDFA(int decision, int numStates, int[] accepts, int[] fallbacks, - int[] edgeOffsets, int[] edges, boolean cyclic, int maxK) { + public StaticDFA(int decision, int numStates, int[] accepts, long[] acceptMasks, + int[] fallbacks, int[] edgeOffsets, int[] edges, boolean cyclic, int maxK) { this.decision = decision; this.numStates = numStates; this.accepts = accepts; + this.acceptMasks = acceptMasks; this.fallbacks = fallbacks; this.edgeOffsets = edgeOffsets; this.edges = edges; diff --git a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java index e5dfc2d523..47e57fca36 100644 --- a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java +++ b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java @@ -41,6 +41,15 @@ * fallbacks[numStates] (error-avoidance alt per state; 0 = none) * edgeOffsets[numStates+1] (index of each state's first edge int) * edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) + * numMaskStates (states accepting with an alternative + * mask instead of a unique alt: the live + * set is covered by one prefix-factor + * group; the parser executes the shared + * prefix and resolves at the tail decision) + * for each mask state: (sorted by state index) + * state + * numAlts + * alts[numAlts] (the group's member alternatives) * numPrecedenceDispatches * for each dispatch: (a left-recursive precedence loop decision) * decision @@ -54,7 +63,8 @@ * their table index.

*/ public class SerializedStaticDFAs extends OutputModelObject { - public static final int FORMAT_VERSION = 5; + /** v6: per-table alternative-mask section (prefix-factor groups). */ + public static final int FORMAT_VERSION = 6; public final int numTables; /** Base64 text segments of the serialized blob, one rendered per line. */ @@ -141,6 +151,23 @@ public static int appendIntStream(Map dfas, for (int v : dfa.fallbacks) data.add(v); for (int v : dfa.edgeOffsets) data.add(v); for (int v : dfa.edges) data.add(v); + // alternative-mask section (v6) + int numMaskStates = 0; + for (long m : dfa.acceptMasks) { + if (m != 0) numMaskStates++; + } + data.add(numMaskStates); + if (numMaskStates > 0) { + for (int s = 0; s < dfa.numStates; s++) { + long m = dfa.acceptMasks[s]; + if (m == 0) continue; + data.add(s); + data.add(Long.bitCount(m)); + for (int a = 0; a < 64; a++) { + if ((m & (1L << a)) != 0) data.add(a+1); + } + } + } int escapes = 0; for (int v : dfa.accepts) { if (v == StaticDFA.ESCAPE) escapes++; @@ -149,7 +176,8 @@ public static int appendIntStream(Map dfas, ? "decision "+dfa.decision : "table "+i+" (decision "+dfa.decision+")") +": "+(dfa.cyclic ? "LL(*) cyclic" : "LL(k), k="+dfa.maxK) +", "+dfa.numStates+" states" - +(escapes > 0 ? ", "+escapes+" adaptive escapes" : "")); + +(escapes > 0 ? ", "+escapes+" adaptive escapes" : "") + +(numMaskStates > 0 ? ", "+numMaskStates+" mask accepts" : "")); } data.add(dispatches.size()); for (int[] entry : dispatches) { @@ -163,6 +191,7 @@ private static int indexOf(List tables, StaticDFA t) { for (int i = 0; i < tables.size(); i++) { StaticDFA o = tables.get(i); if (o == t || (Arrays.equals(o.accepts, t.accepts) + && Arrays.equals(o.acceptMasks, t.acceptMasks) && Arrays.equals(o.fallbacks, t.fallbacks) && Arrays.equals(o.edgeOffsets, t.edgeOffsets) && Arrays.equals(o.edges, t.edges))) { From 53b9a4e802cad368ad479b3e286324b8f160df15 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 18 Jul 2026 22:08:19 -0400 Subject: [PATCH 17/48] Factored alt-mask codegen: implied left-factoring for prefix-group decisions Decisions with a validated prefix-factor plan (M0/M1) now get a FactoredAltBlock in the Rust codegen: the prediction call uses the mask protocol (dfa_predict_mask), singleton masks take the ordinary alternative arms, and each group mask takes a factored arm that executes the shared prefix once and resolves the choice with the group's LL(1) tail switch, specializing the label context in place (copy_from). The adaptive fallback widens its unique answer to a singleton bit and routes through the same arms. The shared rule invocation pushes a synthetic call-site state (a BasicState with a RuleTransition to the shared rule) whose follow is a synthetic tail-decision state spanning every member's tail (epsilon transitions to each tail start). Without it, nested adaptive simulations inside the shared invocation prune against one member's alternative continuation - e.g. 'SELECT (-1)' dying because the rowConstructor continuation wants ',' instead of ')'. The states are appended to the grammar ATN at table-build time and are unreachable from any rule start. Verified: Trino d=316's hot state resolves in-table via mask {2,25}; 1200 generated paren-heavy queries plus the 1690-input corpus are static/adaptive identical (the two pre-existing '::' error-path divergences excepted, from the enter/exit substitution work); the new ParenExpr witness grammar's differential corners (nested parens, subqueries, row constructors, unary minus, error inputs) all pass; cargo test green (11 suites); Send witness unchanged; Q1 perf stable (Trino 2.2us, Duckdb 2.4us). Signed-off-by: Bo Lin --- runtime/Rust/gen_test_grammars.sh | 8 + runtime/Rust/grammars/ParenExpr.g4 | 44 + .../gen/adaptive/parenexprbaselistener.rs | 155 ++ .../Rust/tests/gen/adaptive/parenexprlexer.rs | 136 ++ .../tests/gen/adaptive/parenexprlistener.rs | 130 ++ .../tests/gen/adaptive/parenexprparser.rs | 1838 ++++++++++++++++ .../Rust/tests/gen/parenexprbaselistener.rs | 155 ++ runtime/Rust/tests/gen/parenexprlexer.rs | 136 ++ runtime/Rust/tests/gen/parenexprlistener.rs | 130 ++ runtime/Rust/tests/gen/parenexprparser.rs | 1892 +++++++++++++++++ .../Rust/tests/paren_differential_tests.rs | 112 + .../v4/tool/templates/codegen/Rust/Rust.stg | 41 + .../antlr/v4/analysis/DecisionClassifier.java | 54 +- .../v4/analysis/PrefixFactorAnalyzer.java | 16 + .../v4/codegen/OutputModelController.java | 179 ++ .../v4/codegen/model/FactoredAltBlock.java | 50 + .../antlr/v4/codegen/model/FactoredGroup.java | 30 + .../v4/codegen/model/FactoredTailArm.java | 27 + tool/src/org/antlr/v4/tool/Grammar.java | 9 + 19 files changed, 5134 insertions(+), 8 deletions(-) create mode 100644 runtime/Rust/grammars/ParenExpr.g4 create mode 100644 runtime/Rust/tests/gen/adaptive/parenexprbaselistener.rs create mode 100644 runtime/Rust/tests/gen/adaptive/parenexprlexer.rs create mode 100644 runtime/Rust/tests/gen/adaptive/parenexprlistener.rs create mode 100644 runtime/Rust/tests/gen/adaptive/parenexprparser.rs create mode 100644 runtime/Rust/tests/gen/parenexprbaselistener.rs create mode 100644 runtime/Rust/tests/gen/parenexprlexer.rs create mode 100644 runtime/Rust/tests/gen/parenexprlistener.rs create mode 100644 runtime/Rust/tests/gen/parenexprparser.rs create mode 100644 runtime/Rust/tests/paren_differential_tests.rs create mode 100644 tool/src/org/antlr/v4/codegen/model/FactoredAltBlock.java create mode 100644 tool/src/org/antlr/v4/codegen/model/FactoredGroup.java create mode 100644 tool/src/org/antlr/v4/codegen/model/FactoredTailArm.java diff --git a/runtime/Rust/gen_test_grammars.sh b/runtime/Rust/gen_test_grammars.sh index b474f5e26b..7a9c335afe 100755 --- a/runtime/Rust/gen_test_grammars.sh +++ b/runtime/Rust/gen_test_grammars.sh @@ -17,6 +17,7 @@ declare -a GRAMMARS=( "LrDfa" "FuzzExpr" "BetweenExpr" + "ParenExpr" # "FHIRPath" ) @@ -32,6 +33,7 @@ declare -a ADDITIONAL_ARGS=( "-Xstatic-dfa" "-Xstatic-dfa" "-Xstatic-dfa" + "-Xstatic-dfa" ) for i in "${!GRAMMARS[@]}"; do @@ -60,3 +62,9 @@ echo "Generating: FuzzExpr (adaptive twin)" echo "Generating: BetweenExpr (adaptive twin)" (cd "$SCRIPT_DIR/grammars" && java -cp "$ANTLR_PATH" org.antlr.v4.Tool -Dlanguage=Rust \ -o ../tests/gen/adaptive BetweenExpr.g4) + +# Same differential twin for the paren-family alt-mask grammar +# (tests/paren_differential_tests.rs). +echo "Generating: ParenExpr (adaptive twin)" +(cd "$SCRIPT_DIR/grammars" && java -cp "$ANTLR_PATH" org.antlr.v4.Tool -Dlanguage=Rust \ + -o ../tests/gen/adaptive ParenExpr.g4) diff --git a/runtime/Rust/grammars/ParenExpr.g4 b/runtime/Rust/grammars/ParenExpr.g4 new file mode 100644 index 0000000000..73aac9191d --- /dev/null +++ b/runtime/Rust/grammars/ParenExpr.g4 @@ -0,0 +1,44 @@ +// Differential-test grammar for alt-mask prediction ("implied +// left-factoring", see PrefixFactorAnalyzer and FactoredAltBlock): +// the primary block of a left-recursive expression rule with a +// parenthesized family +// +// '(' expr (',' expr)+ ')' (row constructor) +// '(' expr ')' (plain parens) +// '(' query ')' (subquery) +// +// The row-constructor and paren alternatives share the unbounded prefix +// '(' expr, so the primary decision cannot be statically resolved to a +// unique alternative: distinguishing them needs the token after the +// full expression (',' vs ')'). The subquery alternative keeps pace +// whenever the content can start a query (identifiers - a parenthesized +// table name is a valid query). With -Xstatic-dfa, the tool proves the +// group ('(' expr shared, tails ',' vs ')' LL(1)-disjoint) and the +// table accepts with the alt mask {rowConstructor, parens} once the +// subquery reading dies; the generated factored arm executes '(' expr +// once and resolves the choice with a k=1 tail switch. Deep nesting +// ('((((((x)))))') keeps the subquery reading alive arbitrarily long; +// those paths still escape to adaptivePredict, and both engines must +// agree on every corner (tests/paren_differential_tests.rs). +grammar ParenExpr; + +s : e EOF ; + +e : INT # num + | ID # col + | '(' e (',' e)+ ')' # rowConstructor + | '(' e ')' # parens + | '(' q ')' # subquery + | '-' e # unary + | e ('*'|'/') e # mul + | e ('+'|'-') e # add + ; + +q : 'SELECT' ID # select + | ID # table + | '(' q ')' # nested + ; + +ID : [a-z]+ ; +INT : [0-9]+ ; +WS : [ \t\n]+ -> skip ; diff --git a/runtime/Rust/tests/gen/adaptive/parenexprbaselistener.rs b/runtime/Rust/tests/gen/adaptive/parenexprbaselistener.rs new file mode 100644 index 0000000000..aa3429de1b --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/parenexprbaselistener.rs @@ -0,0 +1,155 @@ +// Generated from ParenExpr.g4 by ANTLR 4.13.2 + +use super::parenexprparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by ParenExprParser. + +pub trait ParenExprBaseListener<'arena>: + ParseTreeListener<'arena, ParenExprParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_add(&mut self, _ctx: &AddContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_add(&mut self, _ctx: &AddContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_col(&mut self, _ctx: &ColContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_col(&mut self, _ctx: &ColContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_parens(&mut self, _ctx: &ParensContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_parens(&mut self, _ctx: &ParensContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_subquery(&mut self, _ctx: &SubqueryContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_subquery(&mut self, _ctx: &SubqueryContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_rowconstructor(&mut self, _ctx: &RowConstructorContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_rowconstructor(&mut self, _ctx: &RowConstructorContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_mul(&mut self, _ctx: &MulContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_mul(&mut self, _ctx: &MulContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_num(&mut self, _ctx: &NumContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_num(&mut self, _ctx: &NumContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_unary(&mut self, _ctx: &UnaryContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_unary(&mut self, _ctx: &UnaryContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_select(&mut self, _ctx: &SelectContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_select(&mut self, _ctx: &SelectContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_table(&mut self, _ctx: &TableContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_table(&mut self, _ctx: &TableContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_nested(&mut self, _ctx: &NestedContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_nested(&mut self, _ctx: &NestedContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/adaptive/parenexprlexer.rs b/runtime/Rust/tests/gen/adaptive/parenexprlexer.rs new file mode 100644 index 0000000000..1bc467cf59 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/parenexprlexer.rs @@ -0,0 +1,136 @@ +// Generated from ParenExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const ID:i32=9; +pub const INT:i32=10; +pub const WS:i32=11; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;11] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "ID", + "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;9] = [ + None, Some("'('"), Some("','"), Some("')'"), Some("'-'"), Some("'*'"), + Some("'/'"), Some("'+'"), Some("'SELECT'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;12] = [ + None, None, None, None, None, None, None, None, None, Some("ID"), Some("INT"), + Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, ParenExprLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct ParenExprLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { ParenExprLexer } +dbt_antlr4::impl_deref! { lexer => ParenExprLexer } + +impl<'input, 'arena, Input, TF> ParenExprLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = ParenExprLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct ParenExprLexerActions { +} + +impl ParenExprLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for ParenExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for ParenExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "ParenExprLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 10] = [ + "CAAWegwBBAAOAAQCDgIEBA4EBAYOBgQIDggECg4KBAwODAQODg4EEA4QBBIOEgQUDhQCAAIAAgICAgIE", + "AgQCBgIGAggCCAIKAgoCDAIMAg4CDgIOAg4CDgIOAg4CEAgQXBAQFhAYEF4CEggSZhASFhIYEmgCFAgU", + "cBAUFhQYFHICFAIUAAAWAgIGBAoGDggSChYMGg4eECISJhQqFgIABgIAwgH0AQIAYHIEABIUQEB+AAIC", + "AAAAAAYCAAAAAAoCAAAAAA4CAAAAABICAAAAABYCAAAAABoCAAAAAB4CAAAAACICAAAAACYCAAAAACoC", + "AAAAAi4CAAAABjICAAAACjYCAAAADjoCAAAAEj4CAAAAFkICAAAAGkYCAAAAHkoCAAAAIloCAAAAJmQC", + "AAAAKm4CAAAALjAKUAAAMAQCAAAAMjQKWAAANAgCAAAANjgKUgAAOAwCAAAAOjwKWgAAPBACAAAAPkAK", + "VAAAQBQCAAAAQkQKXgAARBgCAAAARkgKVgAASBwCAAAASkwKpgEAAExOCooBAABOUAqYAQAAUFIKigEA", + "AFJUCoYBAABUVgqoAQAAViACAAAAWFwOAAAAWlgCAAAAXF4CAAAAXloCAAAAXmACAAAAYCQCAAAAYmYO", + "AgAAZGICAAAAZmgCAAAAaGQCAAAAaGoCAAAAaigCAAAAbHAOBAAAbmwCAAAAcHICAAAAcm4CAAAAcnQC", + "AAAAdHYCAAAAdngMFAAAeCwCAAAACABeaHICDAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/adaptive/parenexprlistener.rs b/runtime/Rust/tests/gen/adaptive/parenexprlistener.rs new file mode 100644 index 0000000000..a7eec21e3b --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/parenexprlistener.rs @@ -0,0 +1,130 @@ +#![allow(nonstandard_style)] +// Generated from ParenExpr.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::parenexprparser::*; + +pub trait ParenExprListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, ParenExprParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link ParenExprParser#s}. + /// @param ctx the parse tree + fn enter_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link ParenExprParser#s}. + /// @param ctx the parse tree + fn exit_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code add} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_add<'input: 'arena>(&mut self, _ctx: &AddContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code add} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_add<'input: 'arena>(&mut self, _ctx: &AddContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code col} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_col<'input: 'arena>(&mut self, _ctx: &ColContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code col} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_col<'input: 'arena>(&mut self, _ctx: &ColContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code parens} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_parens<'input: 'arena>(&mut self, _ctx: &ParensContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code parens} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_parens<'input: 'arena>(&mut self, _ctx: &ParensContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code subquery} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_subquery<'input: 'arena>(&mut self, _ctx: &SubqueryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code subquery} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_subquery<'input: 'arena>(&mut self, _ctx: &SubqueryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code rowConstructor} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_rowConstructor<'input: 'arena>(&mut self, _ctx: &RowConstructorContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code rowConstructor} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_rowConstructor<'input: 'arena>(&mut self, _ctx: &RowConstructorContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code mul} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_mul<'input: 'arena>(&mut self, _ctx: &MulContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code mul} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_mul<'input: 'arena>(&mut self, _ctx: &MulContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code num} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_num<'input: 'arena>(&mut self, _ctx: &NumContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code num} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_num<'input: 'arena>(&mut self, _ctx: &NumContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code unary} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_unary<'input: 'arena>(&mut self, _ctx: &UnaryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code unary} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_unary<'input: 'arena>(&mut self, _ctx: &UnaryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code select} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn enter_select<'input: 'arena>(&mut self, _ctx: &SelectContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code select} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn exit_select<'input: 'arena>(&mut self, _ctx: &SelectContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code table} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn enter_table<'input: 'arena>(&mut self, _ctx: &TableContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code table} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn exit_table<'input: 'arena>(&mut self, _ctx: &TableContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code nested} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn enter_nested<'input: 'arena>(&mut self, _ctx: &NestedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code nested} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn exit_nested<'input: 'arena>(&mut self, _ctx: &NestedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/adaptive/parenexprparser.rs b/runtime/Rust/tests/gen/adaptive/parenexprparser.rs new file mode 100644 index 0000000000..9a97302787 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/parenexprparser.rs @@ -0,0 +1,1838 @@ +// Generated from ParenExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::parenexprlistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const ParenExpr_T__0:i32=1; +pub const ParenExpr_T__1:i32=2; +pub const ParenExpr_T__2:i32=3; +pub const ParenExpr_T__3:i32=4; +pub const ParenExpr_T__4:i32=5; +pub const ParenExpr_T__5:i32=6; +pub const ParenExpr_T__6:i32=7; +pub const ParenExpr_T__7:i32=8; +pub const ParenExpr_ID:i32=9; +pub const ParenExpr_INT:i32=10; +pub const ParenExpr_WS:i32=11; +pub const ParenExpr_EOF:i32=EOF; +pub const RULE_s:usize = 0; +pub const RULE_e:usize = 1; +pub const RULE_q:usize = 2; +pub const ruleNames: [&'static str; 3] = [ + "s", "e", "q" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;9] = [ + None, Some("'('"), Some("','"), Some("')'"), Some("'-'"), Some("'*'"), + Some("'/'"), Some("'+'"), Some("'SELECT'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;12] = [ + None, None, None, None, None, None, None, None, None, Some("ID"), Some("INT"), + Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, ParenExprParserExt<'input, 'arena>, ParenExprParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + ParenExprParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: ParenExprListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct ParenExprTreeWalker; +impl ParenExprTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: ParenExprListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, ParenExprParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum ParenExprParserNodeKind { + SContext, + EContext, + QContext, + Terminal, + Error, +} +pub type ParenExprParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, ParenExprParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => ParenExprParser } +dbt_antlr4::impl_node_kind! { ParenExprParserNodeKind { + EContext(EContextAll), QContext(QContextAll), ; SContext(enter_s, exit_s, ), + }; listener = dyn ParenExprListener<'arena, Tok>, +} + +pub struct ParenExprParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> ParenExprParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ParenExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ParenExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "ParenExpr.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena ParenExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 1 => ParenExprParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn e_sempred(_ctx: Option<&'arena EContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 2) + } + 1 => { + recog.precpred(None, 1) + } + _ => true + } + } +} +//------------------- s ---------------- +pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; + +pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::SContext } + fn get_rule_index(&self) -> usize { RULE_s } + fn make_node( + arena: &'arena Arena, + ctx: SContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { + ph: PhantomData + } + ) + } +} + +pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> SContextAttrs<'input, 'arena, Tok> for SContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_EOF) + } +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(6); + recog.e_rec(0)?; + recog.base.set_state(7); + recog.base.match_token(ParenExpr_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- e ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum EContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + AddContext(AddContext<'input, 'arena, Tok>), + ColContext(ColContext<'input, 'arena, Tok>), + ParensContext(ParensContext<'input, 'arena, Tok>), + SubqueryContext(SubqueryContext<'input, 'arena, Tok>), + RowConstructorContext(RowConstructorContext<'input, 'arena, Tok>), + MulContext(MulContext<'input, 'arena, Tok>), + NumContext(NumContext<'input, 'arena, Tok>), + UnaryContext(UnaryContext<'input, 'arena, Tok>), + Error(EContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { EContextAll { } { AddContext, ColContext, ParensContext, SubqueryContext, RowConstructorContext, MulContext, NumContext, UnaryContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { EContextAll { } { AddContext, ColContext, ParensContext, SubqueryContext, RowConstructorContext, MulContext, NumContext, UnaryContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { ParenExprParserNodeKind::EContextAll { AddContext, ColContext, ParensContext, SubqueryContext, RowConstructorContext, MulContext, NumContext, UnaryContext, Error, } } +dbt_antlr4::impl_node_inner! { ParenExprParserNodeKind::EContext::EContextAll { AddContext, ColContext, ParensContext, SubqueryContext, RowConstructorContext, MulContext, NumContext, UnaryContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { ParenExprListener::ParenExprParserNodeKind::EContextAll { AddContext(enter_add, exit_add), ColContext(enter_col, exit_col), ParensContext(enter_parens, exit_parens), SubqueryContext(enter_subquery, exit_subquery), RowConstructorContext(enter_rowConstructor, exit_rowConstructor), MulContext(enter_mul, exit_mul), NumContext(enter_num, exit_num), UnaryContext(enter_unary, exit_unary), } } + +impl<'input, 'arena, Tok> Deref for EContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn EContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use EContextAll::*; + match self{ + AddContext(inner) => inner, + ColContext(inner) => inner, + ParensContext(inner) => inner, + SubqueryContext(inner) => inner, + RowConstructorContext(inner) => inner, + MulContext(inner) => inner, + NumContext(inner) => inner, + UnaryContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type EContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: EContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, EContextExt { + ph: PhantomData + } + ) + } +} + +pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> EContextAttrs<'input, 'arena, Tok> for EContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type AddContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AddContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait AddContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AddContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AddContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: AddContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::AddContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AddContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::AddContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AddContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::AddContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::AddContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type ColContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ColContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait ColContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ColContextAttrs<'input, 'arena, Tok> for ColContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_ID) + } +} +#[derive(Debug)] +pub struct ColContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ColContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: ColContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::ColContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ColContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::ColContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ColContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::ColContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ColContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ColContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::ColContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type ParensContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ParensContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait ParensContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ParensContextAttrs<'input, 'arena, Tok> for ParensContext<'input, 'arena, Tok> +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct ParensContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ParensContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: ParensContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::ParensContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ParensContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::ParensContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ParensContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::ParensContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ParensContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ParensContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::ParensContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type SubqueryContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SubqueryContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait SubqueryContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SubqueryContextAttrs<'input, 'arena, Tok> for SubqueryContext<'input, 'arena, Tok> +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct SubqueryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for SubqueryContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: SubqueryContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::SubqueryContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SubqueryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::SubqueryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SubqueryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::SubqueryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for SubqueryContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SubqueryContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::SubqueryContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type RowConstructorContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, RowConstructorContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait RowConstructorContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> RowConstructorContextAttrs<'input, 'arena, Tok> for RowConstructorContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct RowConstructorContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for RowConstructorContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: RowConstructorContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::RowConstructorContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a RowConstructorContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::RowConstructorContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut RowConstructorContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::RowConstructorContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for RowConstructorContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> RowConstructorContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::RowConstructorContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type MulContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, MulContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait MulContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct MulContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for MulContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: MulContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::MulContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a MulContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::MulContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut MulContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::MulContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::MulContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type NumContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NumContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait NumContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NumContextAttrs<'input, 'arena, Tok> for NumContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_INT) + } +} +#[derive(Debug)] +pub struct NumContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NumContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: NumContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::NumContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NumContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::NumContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NumContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::NumContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for NumContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NumContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::NumContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type UnaryContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, UnaryContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait UnaryContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> UnaryContextAttrs<'input, 'arena, Tok> for UnaryContext<'input, 'arena, Tok> +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct UnaryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for UnaryContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: UnaryContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::UnaryContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a UnaryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::UnaryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut UnaryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::UnaryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for UnaryContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> UnaryContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::UnaryContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.e_rec(0) + } + + fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 2; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(1,&mut recog.base)? { + 1 =>{ + { + recog.base.with_mut_ctx(|ctx| { NumContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NumContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(10); + recog.base.match_token(ParenExpr_INT,&mut recog.err_handler)?; + } + } + , + 2 =>{ + { + recog.base.with_mut_ctx(|ctx| { ColContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ColContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(11); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + } + } + , + 3 =>{ + { + recog.base.with_mut_ctx(|ctx| { RowConstructorContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena RowConstructorContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(12); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(13); + recog.e_rec(0)?; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { + { + { + recog.base.set_state(14); + recog.base.match_token(ParenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(15); + recog.e_rec(0)?; + } + } + recog.base.set_state(18); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !(_la==ParenExpr_T__1) {break} + } + recog.base.set_state(20); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + } + , + 4 =>{ + { + recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(22); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(23); + recog.e_rec(0)?; + recog.base.set_state(24); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + } + , + 5 =>{ + { + recog.base.with_mut_ctx(|ctx| { SubqueryContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena SubqueryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(26); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule q*/ + recog.base.set_state(27); + recog.q()?; + recog.base.set_state(28); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + } + , + 6 =>{ + { + recog.base.with_mut_ctx(|ctx| { UnaryContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena UnaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(30); + recog.base.match_token(ParenExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(31); + recog.e_rec(3)?; + } + } + + _ => {} + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(42); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(40); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + MulContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(34); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(35); + _la = recog.base.input.la(1); + if { !(_la==ParenExpr_T__4 || _la==ParenExpr_T__5) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(36); + recog.e_rec(3)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AddContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(37); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(38); + _la = recog.base.input.la(1); + if { !(_la==ParenExpr_T__3 || _la==ParenExpr_T__6) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(39); + recog.e_rec(2)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(44); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- q ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum QContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + SelectContext(SelectContext<'input, 'arena, Tok>), + NestedContext(NestedContext<'input, 'arena, Tok>), + TableContext(TableContext<'input, 'arena, Tok>), + Error(QContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { QContextAll { } { SelectContext, NestedContext, TableContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { QContextAll { } { SelectContext, NestedContext, TableContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { ParenExprParserNodeKind::QContextAll { SelectContext, NestedContext, TableContext, Error, } } +dbt_antlr4::impl_node_inner! { ParenExprParserNodeKind::QContext::QContextAll { SelectContext, NestedContext, TableContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { ParenExprListener::ParenExprParserNodeKind::QContextAll { SelectContext(enter_select, exit_select), NestedContext(enter_nested, exit_nested), TableContext(enter_table, exit_table), } } + +impl<'input, 'arena, Tok> Deref for QContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn QContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use QContextAll::*; + match self{ + SelectContext(inner) => inner, + NestedContext(inner) => inner, + TableContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type QContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, QContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct QContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for QContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: QContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(QContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a QContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => QContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut QContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut QContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, QContextExt { + ph: PhantomData + } + ) + } +} + +pub trait QContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> QContextAttrs<'input, 'arena, Tok> for QContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type SelectContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SelectContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait SelectContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SelectContextAttrs<'input, 'arena, Tok> for SelectContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_ID) + } +} +#[derive(Debug)] +pub struct SelectContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: QContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for SelectContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: SelectContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(QContextAll::SelectContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SelectContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { + QContextAll::SelectContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SelectContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { + QContextAll::SelectContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for SelectContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SelectContextExt<'input, 'arena, Tok> { + fn new(base: QContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut QContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + QContextAll::SelectContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type NestedContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NestedContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait NestedContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NestedContextAttrs<'input, 'arena, Tok> for NestedContext<'input, 'arena, Tok> +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct NestedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: QContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NestedContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: NestedContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(QContextAll::NestedContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NestedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { + QContextAll::NestedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NestedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { + QContextAll::NestedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for NestedContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NestedContextExt<'input, 'arena, Tok> { + fn new(base: QContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut QContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + QContextAll::NestedContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type TableContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, TableContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait TableContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> TableContextAttrs<'input, 'arena, Tok> for TableContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_ID) + } +} +#[derive(Debug)] +pub struct TableContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: QContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for TableContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: TableContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(QContextAll::TableContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a TableContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { + QContextAll::TableContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut TableContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { + QContextAll::TableContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for TableContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> TableContextExt<'input, 'arena, Tok> { + fn new(base: QContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut QContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + QContextAll::TableContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn q(&mut self,) -> Result<&'arena QContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(QContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_q)?; + let _local_ctx_fn = |recog: &Self| -> &'arena QContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(52); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + ParenExpr_T__7 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + SelectContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena SelectContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(45); + recog.base.match_token(ParenExpr_T__7,&mut recog.err_handler)?; + recog.base.set_state(46); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + }} + ParenExpr_ID => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + TableContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena TableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(47); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + }} + ParenExpr_T__0 => { + /*------- Outer Most Alt 3 -------*/ + recog.base.with_mut_ctx(|ctx| { + NestedContextExt::copy_from(ctx); + ctx.set_alt_number(3); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena NestedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(48); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule q*/ + recog.base.set_state(49); + recog.q()?; + recog.base.set_state(50); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 9] = [ + "CAIWbgQADgAEAg4CBAQOBAIAAgACAAICAgICAgICAgICAgICCAIiEAIWAhgCJAICAgICAgICAgICAgIC", + "AgICAgICAgICAgYCQhACAgICAgICAgICAgICCgJSEAIUAhgCWBICAgQCBAIEAgQCBAIEAgQGBGoQBAIE", + "AAIEBgAECAAEAgAKDAQACAgODnoADAIAAAAEQAIAAAAIaAIAAAAMDgYEAgAOEAoAAAIQAgIAAAASFAwC", + "AQAUQgoUAAAWQgoSAAAYGgoCAAAaIAYEAgAcHgoEAAAeIgYEAgAgHAIAAAAiJAIAAAAkIAIAAAAkJgIA", + "AAAmKAIAAAAoKgoGAAAqQgIAAAAsLgoCAAAuMAYEAgAwMgoGAAAyQgIAAAA0NgoCAAA2OAYIBAA4OgoG", + "AAA6QgIAAAA8PgoIAAA+QgYEAgZAEgIAAABAFgIAAABAGAIAAABALAIAAABANAIAAABAPAIAAABCVAIA", + "AABERhQEAABGSA4AAABIUgYEAgZKTBQCAABMTg4CAABOUgYEAgRQRAIAAABQSgIAAABSWAIAAABUUAIA", + "AABUVgIAAABWBgIAAABYVAIAAABaXAoQAABcagoSAABeagoSAABgYgoCAABiZAYIBABkZgoGAABmagIA", + "AABoWgIAAABoXgIAAABoYAIAAABqCgIAAAAKJEBQVGg=" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/parenexprbaselistener.rs b/runtime/Rust/tests/gen/parenexprbaselistener.rs new file mode 100644 index 0000000000..aa3429de1b --- /dev/null +++ b/runtime/Rust/tests/gen/parenexprbaselistener.rs @@ -0,0 +1,155 @@ +// Generated from ParenExpr.g4 by ANTLR 4.13.2 + +use super::parenexprparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by ParenExprParser. + +pub trait ParenExprBaseListener<'arena>: + ParseTreeListener<'arena, ParenExprParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_s(&mut self, _ctx: &SContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_add(&mut self, _ctx: &AddContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_add(&mut self, _ctx: &AddContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_col(&mut self, _ctx: &ColContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_col(&mut self, _ctx: &ColContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_parens(&mut self, _ctx: &ParensContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_parens(&mut self, _ctx: &ParensContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_subquery(&mut self, _ctx: &SubqueryContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_subquery(&mut self, _ctx: &SubqueryContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_rowconstructor(&mut self, _ctx: &RowConstructorContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_rowconstructor(&mut self, _ctx: &RowConstructorContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_mul(&mut self, _ctx: &MulContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_mul(&mut self, _ctx: &MulContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_num(&mut self, _ctx: &NumContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_num(&mut self, _ctx: &NumContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_unary(&mut self, _ctx: &UnaryContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_unary(&mut self, _ctx: &UnaryContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_select(&mut self, _ctx: &SelectContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_select(&mut self, _ctx: &SelectContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_table(&mut self, _ctx: &TableContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_table(&mut self, _ctx: &TableContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_nested(&mut self, _ctx: &NestedContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link ParenExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_nested(&mut self, _ctx: &NestedContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/parenexprlexer.rs b/runtime/Rust/tests/gen/parenexprlexer.rs new file mode 100644 index 0000000000..1bc467cf59 --- /dev/null +++ b/runtime/Rust/tests/gen/parenexprlexer.rs @@ -0,0 +1,136 @@ +// Generated from ParenExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const ID:i32=9; +pub const INT:i32=10; +pub const WS:i32=11; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;11] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "ID", + "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;9] = [ + None, Some("'('"), Some("','"), Some("')'"), Some("'-'"), Some("'*'"), + Some("'/'"), Some("'+'"), Some("'SELECT'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;12] = [ + None, None, None, None, None, None, None, None, None, Some("ID"), Some("INT"), + Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, ParenExprLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct ParenExprLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { ParenExprLexer } +dbt_antlr4::impl_deref! { lexer => ParenExprLexer } + +impl<'input, 'arena, Input, TF> ParenExprLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = ParenExprLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct ParenExprLexerActions { +} + +impl ParenExprLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for ParenExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for ParenExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "ParenExprLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 10] = [ + "CAAWegwBBAAOAAQCDgIEBA4EBAYOBgQIDggECg4KBAwODAQODg4EEA4QBBIOEgQUDhQCAAIAAgICAgIE", + "AgQCBgIGAggCCAIKAgoCDAIMAg4CDgIOAg4CDgIOAg4CEAgQXBAQFhAYEF4CEggSZhASFhIYEmgCFAgU", + "cBAUFhQYFHICFAIUAAAWAgIGBAoGDggSChYMGg4eECISJhQqFgIABgIAwgH0AQIAYHIEABIUQEB+AAIC", + "AAAAAAYCAAAAAAoCAAAAAA4CAAAAABICAAAAABYCAAAAABoCAAAAAB4CAAAAACICAAAAACYCAAAAACoC", + "AAAAAi4CAAAABjICAAAACjYCAAAADjoCAAAAEj4CAAAAFkICAAAAGkYCAAAAHkoCAAAAIloCAAAAJmQC", + "AAAAKm4CAAAALjAKUAAAMAQCAAAAMjQKWAAANAgCAAAANjgKUgAAOAwCAAAAOjwKWgAAPBACAAAAPkAK", + "VAAAQBQCAAAAQkQKXgAARBgCAAAARkgKVgAASBwCAAAASkwKpgEAAExOCooBAABOUAqYAQAAUFIKigEA", + "AFJUCoYBAABUVgqoAQAAViACAAAAWFwOAAAAWlgCAAAAXF4CAAAAXloCAAAAXmACAAAAYCQCAAAAYmYO", + "AgAAZGICAAAAZmgCAAAAaGQCAAAAaGoCAAAAaigCAAAAbHAOBAAAbmwCAAAAcHICAAAAcm4CAAAAcnQC", + "AAAAdHYCAAAAdngMFAAAeCwCAAAACABeaHICDAAA" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/parenexprlistener.rs b/runtime/Rust/tests/gen/parenexprlistener.rs new file mode 100644 index 0000000000..a7eec21e3b --- /dev/null +++ b/runtime/Rust/tests/gen/parenexprlistener.rs @@ -0,0 +1,130 @@ +#![allow(nonstandard_style)] +// Generated from ParenExpr.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::parenexprparser::*; + +pub trait ParenExprListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, ParenExprParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link ParenExprParser#s}. + /// @param ctx the parse tree + fn enter_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link ParenExprParser#s}. + /// @param ctx the parse tree + fn exit_s<'input: 'arena>(&mut self, _ctx: &SContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code add} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_add<'input: 'arena>(&mut self, _ctx: &AddContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code add} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_add<'input: 'arena>(&mut self, _ctx: &AddContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code col} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_col<'input: 'arena>(&mut self, _ctx: &ColContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code col} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_col<'input: 'arena>(&mut self, _ctx: &ColContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code parens} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_parens<'input: 'arena>(&mut self, _ctx: &ParensContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code parens} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_parens<'input: 'arena>(&mut self, _ctx: &ParensContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code subquery} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_subquery<'input: 'arena>(&mut self, _ctx: &SubqueryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code subquery} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_subquery<'input: 'arena>(&mut self, _ctx: &SubqueryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code rowConstructor} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_rowConstructor<'input: 'arena>(&mut self, _ctx: &RowConstructorContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code rowConstructor} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_rowConstructor<'input: 'arena>(&mut self, _ctx: &RowConstructorContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code mul} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_mul<'input: 'arena>(&mut self, _ctx: &MulContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code mul} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_mul<'input: 'arena>(&mut self, _ctx: &MulContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code num} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_num<'input: 'arena>(&mut self, _ctx: &NumContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code num} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_num<'input: 'arena>(&mut self, _ctx: &NumContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code unary} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn enter_unary<'input: 'arena>(&mut self, _ctx: &UnaryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code unary} + /// labeled alternative in {@link ParenExprParser#e}. + /// @param ctx the parse tree + fn exit_unary<'input: 'arena>(&mut self, _ctx: &UnaryContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code select} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn enter_select<'input: 'arena>(&mut self, _ctx: &SelectContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code select} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn exit_select<'input: 'arena>(&mut self, _ctx: &SelectContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code table} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn enter_table<'input: 'arena>(&mut self, _ctx: &TableContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code table} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn exit_table<'input: 'arena>(&mut self, _ctx: &TableContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code nested} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn enter_nested<'input: 'arena>(&mut self, _ctx: &NestedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code nested} + /// labeled alternative in {@link ParenExprParser#q}. + /// @param ctx the parse tree + fn exit_nested<'input: 'arena>(&mut self, _ctx: &NestedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/parenexprparser.rs b/runtime/Rust/tests/gen/parenexprparser.rs new file mode 100644 index 0000000000..f249bc8e95 --- /dev/null +++ b/runtime/Rust/tests/gen/parenexprparser.rs @@ -0,0 +1,1892 @@ +// Generated from ParenExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::parenexprlistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const ParenExpr_T__0:i32=1; +pub const ParenExpr_T__1:i32=2; +pub const ParenExpr_T__2:i32=3; +pub const ParenExpr_T__3:i32=4; +pub const ParenExpr_T__4:i32=5; +pub const ParenExpr_T__5:i32=6; +pub const ParenExpr_T__6:i32=7; +pub const ParenExpr_T__7:i32=8; +pub const ParenExpr_ID:i32=9; +pub const ParenExpr_INT:i32=10; +pub const ParenExpr_WS:i32=11; +pub const ParenExpr_EOF:i32=EOF; +pub const RULE_s:usize = 0; +pub const RULE_e:usize = 1; +pub const RULE_q:usize = 2; +pub const ruleNames: [&'static str; 3] = [ + "s", "e", "q" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;9] = [ + None, Some("'('"), Some("','"), Some("')'"), Some("'-'"), Some("'*'"), + Some("'/'"), Some("'+'"), Some("'SELECT'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;12] = [ + None, None, None, None, None, None, None, None, None, Some("ID"), Some("INT"), + Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, ParenExprParserExt<'input, 'arena>, ParenExprParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + ParenExprParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: ParenExprListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct ParenExprTreeWalker; +impl ParenExprTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: ParenExprListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, ParenExprParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum ParenExprParserNodeKind { + SContext, + EContext, + QContext, + Terminal, + Error, +} +pub type ParenExprParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, ParenExprParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => ParenExprParser } +dbt_antlr4::impl_node_kind! { ParenExprParserNodeKind { + EContext(EContextAll), QContext(QContextAll), ; SContext(enter_s, exit_s, ), + }; listener = dyn ParenExprListener<'arena, Tok>, +} + +pub struct ParenExprParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> ParenExprParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ParenExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ParenExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "ParenExpr.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena ParenExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 1 => ParenExprParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn e_sempred(_ctx: Option<&'arena EContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 2) + } + 1 => { + recog.precpred(None, 1) + } + _ => true + } + } +} +//------------------- s ---------------- +pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; + +pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::SContext } + fn get_rule_index(&self) -> usize { RULE_s } + fn make_node( + arena: &'arena Arena, + ctx: SContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { + ph: PhantomData + } + ) + } +} + +pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> SContextAttrs<'input, 'arena, Tok> for SContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_EOF) + } +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(6); + recog.e_rec(0)?; + recog.base.set_state(7); + recog.base.match_token(ParenExpr_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- e ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum EContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + AddContext(AddContext<'input, 'arena, Tok>), + ColContext(ColContext<'input, 'arena, Tok>), + ParensContext(ParensContext<'input, 'arena, Tok>), + SubqueryContext(SubqueryContext<'input, 'arena, Tok>), + RowConstructorContext(RowConstructorContext<'input, 'arena, Tok>), + MulContext(MulContext<'input, 'arena, Tok>), + NumContext(NumContext<'input, 'arena, Tok>), + UnaryContext(UnaryContext<'input, 'arena, Tok>), + Error(EContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { EContextAll { } { AddContext, ColContext, ParensContext, SubqueryContext, RowConstructorContext, MulContext, NumContext, UnaryContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { EContextAll { } { AddContext, ColContext, ParensContext, SubqueryContext, RowConstructorContext, MulContext, NumContext, UnaryContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { ParenExprParserNodeKind::EContextAll { AddContext, ColContext, ParensContext, SubqueryContext, RowConstructorContext, MulContext, NumContext, UnaryContext, Error, } } +dbt_antlr4::impl_node_inner! { ParenExprParserNodeKind::EContext::EContextAll { AddContext, ColContext, ParensContext, SubqueryContext, RowConstructorContext, MulContext, NumContext, UnaryContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { ParenExprListener::ParenExprParserNodeKind::EContextAll { AddContext(enter_add, exit_add), ColContext(enter_col, exit_col), ParensContext(enter_parens, exit_parens), SubqueryContext(enter_subquery, exit_subquery), RowConstructorContext(enter_rowConstructor, exit_rowConstructor), MulContext(enter_mul, exit_mul), NumContext(enter_num, exit_num), UnaryContext(enter_unary, exit_unary), } } + +impl<'input, 'arena, Tok> Deref for EContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn EContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use EContextAll::*; + match self{ + AddContext(inner) => inner, + ColContext(inner) => inner, + ParensContext(inner) => inner, + SubqueryContext(inner) => inner, + RowConstructorContext(inner) => inner, + MulContext(inner) => inner, + NumContext(inner) => inner, + UnaryContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type EContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: EContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, EContextExt { + ph: PhantomData + } + ) + } +} + +pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> EContextAttrs<'input, 'arena, Tok> for EContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type AddContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AddContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait AddContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AddContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AddContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: AddContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::AddContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AddContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::AddContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AddContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::AddContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::AddContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type ColContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ColContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait ColContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ColContextAttrs<'input, 'arena, Tok> for ColContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_ID) + } +} +#[derive(Debug)] +pub struct ColContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ColContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: ColContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::ColContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ColContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::ColContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ColContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::ColContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ColContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ColContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::ColContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type ParensContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ParensContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait ParensContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ParensContextAttrs<'input, 'arena, Tok> for ParensContext<'input, 'arena, Tok> +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct ParensContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ParensContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: ParensContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::ParensContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ParensContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::ParensContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ParensContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::ParensContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ParensContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ParensContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::ParensContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type SubqueryContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SubqueryContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait SubqueryContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SubqueryContextAttrs<'input, 'arena, Tok> for SubqueryContext<'input, 'arena, Tok> +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct SubqueryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for SubqueryContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: SubqueryContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::SubqueryContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SubqueryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::SubqueryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SubqueryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::SubqueryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for SubqueryContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SubqueryContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::SubqueryContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type RowConstructorContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, RowConstructorContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait RowConstructorContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> RowConstructorContextAttrs<'input, 'arena, Tok> for RowConstructorContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct RowConstructorContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for RowConstructorContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: RowConstructorContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::RowConstructorContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a RowConstructorContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::RowConstructorContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut RowConstructorContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::RowConstructorContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for RowConstructorContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> RowConstructorContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::RowConstructorContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type MulContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, MulContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait MulContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>>; + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> +{ + fn e_all(&self) -> Vec<&'arena EContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn e(&self, i: usize) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct MulContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for MulContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: MulContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::MulContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a MulContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::MulContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut MulContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::MulContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::MulContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type NumContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NumContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait NumContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NumContextAttrs<'input, 'arena, Tok> for NumContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_INT) + } +} +#[derive(Debug)] +pub struct NumContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NumContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: NumContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::NumContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NumContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::NumContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NumContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::NumContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for NumContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NumContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::NumContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type UnaryContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, UnaryContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait UnaryContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> UnaryContextAttrs<'input, 'arena, Tok> for UnaryContext<'input, 'arena, Tok> +{ + fn e(&self) -> Option<&'arena EContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct UnaryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: EContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for UnaryContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } + fn get_rule_index(&self) -> usize { RULE_e } + fn make_node( + arena: &'arena Arena, + ctx: UnaryContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(EContextAll::UnaryContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a UnaryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { + EContextAll::UnaryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut UnaryContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { + EContextAll::UnaryContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for UnaryContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> UnaryContextExt<'input, 'arena, Tok> { + fn new(base: EContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut EContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + EContextAll::UnaryContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.e_rec(0) + } + + fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 2; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + match { let _m = recog.base.dfa_predict_mask(1)?; if _m == 0 { 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) } else { _m } } { + x if x == 0x1 =>{ + { + recog.base.with_mut_ctx(|ctx| { NumContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NumContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(10); + recog.base.match_token(ParenExpr_INT,&mut recog.err_handler)?; + } + }, + x if x == 0x2 =>{ + { + recog.base.with_mut_ctx(|ctx| { ColContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ColContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(11); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + } + }, + x if x == 0x4 =>{ + { + recog.base.with_mut_ctx(|ctx| { RowConstructorContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena RowConstructorContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(12); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(13); + recog.e_rec(0)?; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { + { + { + recog.base.set_state(14); + recog.base.match_token(ParenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(15); + recog.e_rec(0)?; + } + } + recog.base.set_state(18); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !(_la==ParenExpr_T__1) {break} + } + recog.base.set_state(20); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + }, + x if x == 0x8 =>{ + { + recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(22); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(23); + recog.e_rec(0)?; + recog.base.set_state(24); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + }, + x if x == 0x10 =>{ + { + recog.base.with_mut_ctx(|ctx| { SubqueryContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena SubqueryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(26); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule q*/ + recog.base.set_state(27); + recog.q()?; + recog.base.set_state(28); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + }, + x if x == 0x20 =>{ + { + recog.base.with_mut_ctx(|ctx| { UnaryContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena UnaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(30); + recog.base.match_token(ParenExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(31); + recog.e_rec(3)?; + } + } + x if x == 0xc =>{ + { + recog.base.set_state(12); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(56); + recog.e_rec(0)?; + } + match recog.input.la(1) { + ParenExpr_T__1 =>{ + { + recog.base.with_mut_ctx(|ctx| { RowConstructorContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena RowConstructorContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { + { + { + recog.base.set_state(14); + recog.base.match_token(ParenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(15); + recog.e_rec(0)?; + } + } + recog.base.set_state(18); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !(_la==ParenExpr_T__1) {break} + } + recog.base.set_state(20); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + }, + ParenExpr_T__2 =>{ + { + recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(24); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + } + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + } + _ => {} + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(42); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(40); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(2)?; _sdp } { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + MulContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(34); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(35); + _la = recog.base.input.la(1); + if { !(_la==ParenExpr_T__4 || _la==ParenExpr_T__5) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(36); + recog.e_rec(3)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AddContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(37); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(38); + _la = recog.base.input.la(1); + if { !(_la==ParenExpr_T__3 || _la==ParenExpr_T__6) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(39); + recog.e_rec(2)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(44); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- q ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum QContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + SelectContext(SelectContext<'input, 'arena, Tok>), + NestedContext(NestedContext<'input, 'arena, Tok>), + TableContext(TableContext<'input, 'arena, Tok>), + Error(QContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { QContextAll { } { SelectContext, NestedContext, TableContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { QContextAll { } { SelectContext, NestedContext, TableContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { ParenExprParserNodeKind::QContextAll { SelectContext, NestedContext, TableContext, Error, } } +dbt_antlr4::impl_node_inner! { ParenExprParserNodeKind::QContext::QContextAll { SelectContext, NestedContext, TableContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { ParenExprListener::ParenExprParserNodeKind::QContextAll { SelectContext(enter_select, exit_select), NestedContext(enter_nested, exit_nested), TableContext(enter_table, exit_table), } } + +impl<'input, 'arena, Tok> Deref for QContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn QContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use QContextAll::*; + match self{ + SelectContext(inner) => inner, + NestedContext(inner) => inner, + TableContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type QContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, QContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct QContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for QContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: QContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(QContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a QContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => QContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut QContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut QContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, QContextExt { + ph: PhantomData + } + ) + } +} + +pub trait QContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> QContextAttrs<'input, 'arena, Tok> for QContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type SelectContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SelectContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait SelectContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SelectContextAttrs<'input, 'arena, Tok> for SelectContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_ID) + } +} +#[derive(Debug)] +pub struct SelectContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: QContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for SelectContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: SelectContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(QContextAll::SelectContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a SelectContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { + QContextAll::SelectContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut SelectContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { + QContextAll::SelectContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for SelectContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> SelectContextExt<'input, 'arena, Tok> { + fn new(base: QContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut QContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + QContextAll::SelectContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type NestedContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NestedContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait NestedContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NestedContextAttrs<'input, 'arena, Tok> for NestedContext<'input, 'arena, Tok> +{ + fn q(&self) -> Option<&'arena QContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct NestedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: QContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NestedContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: NestedContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(QContextAll::NestedContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NestedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { + QContextAll::NestedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NestedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { + QContextAll::NestedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for NestedContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NestedContextExt<'input, 'arena, Tok> { + fn new(base: QContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut QContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + QContextAll::NestedContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type TableContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, TableContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; + +pub trait TableContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> TableContextAttrs<'input, 'arena, Tok> for TableContext<'input, 'arena, Tok> +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == ParenExpr_ID) + } +} +#[derive(Debug)] +pub struct TableContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: QContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for TableContextExt<'input, 'arena, Tok> +{ + type NodeKind = ParenExprParserNodeKind; + fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } + fn get_rule_index(&self) -> usize { RULE_q } + fn make_node( + arena: &'arena Arena, + ctx: TableContext<'input, 'arena, Tok>, + ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(QContextAll::TableContext(ctx)) + } + fn cast_from<'a>( + node: &'a ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a TableContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { + QContextAll::TableContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut TableContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { + QContextAll::TableContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for TableContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> TableContextExt<'input, 'arena, Tok> { + fn new(base: QContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut ParenExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut QContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + QContextAll::TableContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn q(&mut self,) -> Result<&'arena QContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(QContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_q)?; + let _local_ctx_fn = |recog: &Self| -> &'arena QContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(52); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + ParenExpr_T__7 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + SelectContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena SelectContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(45); + recog.base.match_token(ParenExpr_T__7,&mut recog.err_handler)?; + recog.base.set_state(46); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + }} + ParenExpr_ID => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + TableContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena TableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(47); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + }} + ParenExpr_T__0 => { + /*------- Outer Most Alt 3 -------*/ + recog.base.with_mut_ctx(|ctx| { + NestedContextExt::copy_from(ctx); + ctx.set_alt_number(3); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena NestedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(48); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule q*/ + recog.base.set_state(49); + recog.q()?; + recog.base.set_state(50); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +// the serialized ATN is followed by 5 static SLL prediction tables (-Xstatic-dfa): +// decision 3: precedence-dispatched over cutoffs [1, 2], tables [2 3 4] +// decision 1: LL(k), k=5, 34 states, 4 adaptive escapes, 12 mask accepts +// decision 2: LL(k), k=1, 3 states +// table 2 (decision 3): LL(k), k=1, 5 states +// table 3 (decision 3): LL(k), k=1, 6 states +// table 4 (decision 3): LL(k), k=0, 1 states +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 16] = [ + "CAIWcgQADgAEAg4CBAQOBAIAAgACAAICAgICAgICAgICAgICCAIiEAIWAhgCJAICAgICAgICAgICAgIC", + "AgICAgICAgICAgYCQhACAgICAgICAgICAgICCgJSEAIUAhgCWBICAgQCBAIEAgQCBAIEAgQGBGoQBAIE", + "AgICAgACBAYABAgABAIACgwEAAgIDg6AAQAMAgAAAARAAgAAAAhoAgAAAAwOBgQCAA4QCgAAAhACAgAA", + "ABIUDAIBABRCChQAABZCChIAABgaCgIAABogBgQCABweCgQAAB4iBgQCACAcAgAAACIkAgAAACQgAgAA", + "ACQmAgAAACYoAgAAACgqCgYAACpCAgAAACwuCgIAAC4wBgQCADAyCgYAADJCAgAAADQ2CgIAADY4BggE", + "ADg6CgYAADpCAgAAADw+CggAAD5CBgQCBkASAgAAAEAWAgAAAEAYAgAAAEAsAgAAAEA0AgAAAEA8AgAA", + "AEJUAgAAAERGFAQAAEZIDgAAAEhSBgQCBkpMFAIAAExODgIAAE5SBgQCBFBEAgAAAFBKAgAAAFJYAgAA", + "AFRQAgAAAFRWAgAAAFYGAgAAAFhUAgAAAFpcChAAAFxqChIAAF5qChIAAGBiCgIAAGJkBggEAGRmCgYA", + "AGZqAgAAAGhaAgAAAGheAgAAAGhgAgAAAGoKAgAAAG4gAgAAAG4wAgAAAHBuBgQCAAokQFBUaAwKCAJE", + "9gEAAAwEAgAACgAAAQAAAAAAAAYBAAgAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "AAAAAAAAAAAAAAAYNjY2NlRmZniKAYoBnAGiAbQBxgHkAeQB5AHkAfYB9gH2AfYB9gH2AfYB9gH2AfYB", + "9gH2AfYB9gH2AQICAggIBBISBhQUCAICCggIDBAQDhISEBQUEgICFAgIFhAQGBISGhQUHAICHggIIBIU", + "EgQEIgYGJAgOJgQEIgYGKAgOJgICKggIIBIUHBISLAQELgYGMAgOMgQELgYGNAgOMgICNggIIBAQOBIS", + "OhQUPAICPggIQBIUQhggBAYIKgQGCC4EBggyBAYINAQGCDYEBgg4BAYIOgQGCDwEBgg+BAYIQAQGCEIE", + "BggEBhIABAIAAAAAEhISCAgCCgwEDg4CAAEKGAAEBAQCBAAAAAAAGBgYGBgBAQIEBAQGBgYIDggAAQwk", + "AAQEBAQCBAAAAAAAACQkJCQkJAEBAgQEBAYGBggICAoMCg4OCAABAgAEAAAAAAIGBAIEBAYI" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/paren_differential_tests.rs b/runtime/Rust/tests/paren_differential_tests.rs new file mode 100644 index 0000000000..63cef3cd55 --- /dev/null +++ b/runtime/Rust/tests/paren_differential_tests.rs @@ -0,0 +1,112 @@ +//! Differential corners for alt-mask prediction ("implied +//! left-factoring") on the paren family (grammar `grammars/ParenExpr.g4`, +//! generated twice: `gen/parenexprparser.rs` with `-Xstatic-dfa`, +//! `gen/adaptive/parenexprparser.rs` without). +//! +//! The primary block's rowConstructor (`'(' e (',' e)+ ')'`) and parens +//! (`'(' e ')'`) alternatives share the unbounded prefix `'(' e`; the +//! subquery alternative (`'(' q ')'`) keeps pace on query-shaped content +//! (identifiers included: a parenthesized table name is a valid query). +//! The static table accepts with the alt mask {rowConstructor, parens} +//! once the subquery reading dies, and the generated factored arm +//! executes `'(' e` once and resolves the choice with a k=1 tail switch; +//! deep nesting keeps the subquery reading alive and escapes to +//! adaptivePredict. Both engines must agree on every corner (tree or +//! error). + +#[rustfmt::skip] +mod gen { + #![allow(non_snake_case)] + #![allow(clippy::all)] + pub mod parenexprlexer; + pub mod parenexprlistener; + pub mod parenexprparser; + pub mod adaptive { + pub mod parenexprlexer; + pub mod parenexprlistener; + pub mod parenexprparser; + } +} + +use dbt_antlr4::common_token_stream::CommonTokenStream; +use dbt_antlr4::recognizer::Recognizer; +use dbt_antlr4::token_factory::CommonTokenFactory; +use dbt_antlr4::trees::string_tree; +use dbt_antlr4::{Arena, InputStream}; + +fn parse_static(input: &str) -> Result { + Arena::with(|arena| { + let lexer = gen::parenexprlexer::ParenExprLexer::<_, CommonTokenFactory>::new( + arena, + InputStream::new(input), + ); + let tokens = CommonTokenStream::new(lexer); + let mut parser = gen::parenexprparser::ParenExprParser::new(arena, tokens); + parser + .s() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + .map_err(|e| format!("{e:?}")) + }) +} + +fn parse_adaptive(input: &str) -> Result { + Arena::with(|arena| { + let lexer = gen::adaptive::parenexprlexer::ParenExprLexer::<_, CommonTokenFactory>::new( + arena, + InputStream::new(input), + ); + let tokens = CommonTokenStream::new(lexer); + let mut parser = gen::adaptive::parenexprparser::ParenExprParser::new(arena, tokens); + parser + .s() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + .map_err(|e| format!("{e:?}")) + }) +} + +/// Corners of the paren family. Both engines must agree on every one. +const CORNERS: &[&str] = &[ + // plain parens (alt parens) + "(1)", + "(x)", + "(-1)", + "(1 + 2)", + "((1))", + // row constructors + "(1, 2)", + "(x, y, z)", + "(1, 2, 3, 4)", + "((1, 2), 3)", + // subqueries + "(SELECT t)", + "(t)", + "((SELECT t))", + // the tail decision inside operators + "1 + (2 * 3)", + "(1 + 2) * (3 + 4)", + "-(1, 2)", + "1 * (x, (y, z))", + // nested-paren escapes (subquery reading stays alive arbitrarily + // long; these defer to adaptive and must still agree) + "((((((x))))))", + "((((1, 2))))", + // error corners + "(1,)", + "(1 2)", + "(1, 2", + "(SELECT)", + "(1,)", +]; + +fn check(input: &str) { + let s = parse_static(input); + let a = parse_adaptive(input); + assert_eq!(s, a, "static vs adaptive mismatch on {input:?}"); +} + +#[test] +fn paren_family_corners_agree() { + for corner in CORNERS { + check(corner); + } +} diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index b1f5d1ae74..59b565d343 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -793,6 +793,47 @@ match { } >> +// Mask-protocol prediction for prefix-factorable decisions ("implied +// left-factoring"): dfa_predict_mask returns the set of live +// alternatives as a bitmask (0 = the table defers to the adaptive +// engine; adaptive_predict's unique answer widens to its singleton bit, +// routing through the same arms). +maskPredict(choice) ::= "{ let _m = .base.dfa_predict_mask()?; if _m == 0 { 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) } else { _m }_m }" + +FactoredAltBlock(choice, preamble, singletons, groups, error) ::= << +.base.set_state(); +.err_handler.sync(&mut .base)?; +.base.input.lt(1).map(|t| t as _);})> + +match { + + + _ => {} +} +>> + +SingletonArm(alt, body) ::= << +x if x == =>{ + +\} +>> + +FactoredGroup(grp, prefix, tails) ::= << +x if x == =>{ + + match .input.la(1) { + + _ => Err(ANTLRError::no_alt(&mut .base))? + } +\} +>> + +FactoredTailArm(t, body) ::= << + =>{ + +\} +>> + DFAOptionalBlock(choice, alts, error) ::= << .base.set_state(); .err_handler.sync(&mut .base)?; diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index f5d9b9beac..6e74a64940 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -1182,10 +1182,6 @@ else if (hybridMode) { if (factorGroup != null) { res.factorEscapesCured++; acceptMasks.set(d, altBits(factorGroup.alts)); - if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { - System.err.printf("FACTOR-MASK d=%d state=%d depth=%d alts=%s%n", - s.decision, d, stateDepth.get(d), alts); - } } else { acceptAlts.set(d, StaticDFA.ESCAPE); @@ -1227,10 +1223,6 @@ else if (abortOnUntrustedConflict) { if (factorGroup != null) { res.factorEscapesCured++; acceptMasks.set(d, altBits(factorGroup.alts)); - if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { - System.err.printf("FACTOR-MASK-CAP d=%d state=%d depth=%d alts=%s%n", - s.decision, d, stateDepth.get(d), alts); - } } else { acceptAlts.set(d, StaticDFA.ESCAPE); @@ -2016,6 +2008,8 @@ public static void buildTables(Grammar g) { classifier.abortOnUntrustedConflict = true; Map tables = new LinkedHashMap(); Map precTables = new LinkedHashMap(); + Map factorPlans = + new LinkedHashMap(); for (DecisionState s : g.atn.decisionToState) { // the LL(1) fast path already covers disjoint decisions if (g.decisionLOOK != null && s.decision < g.decisionLOOK.size() @@ -2029,9 +2023,53 @@ public static void buildTables(Grammar g) { else if (r.precDfa != null) { precTables.put(s.decision, r.precDfa); } + if (r.factorPlan != null && r.factorPlan.hasGroups()) { + factorPlans.put(s.decision, r.factorPlan); + } } g.staticDecisionDFAs = tables; g.staticPrecedenceDFAs = precTables; + g.staticFactorPlans = factorPlans; + addSyntheticContinuationStates(g, factorPlans); + } + + /** + * Create, for every group of every factor plan, the two synthetic ATN + * states the factored codegen needs (see + * {@link PrefixFactorAnalyzer.Group#syntheticInvokeState}): the shared + * prefix's rule invocation must push a call-site whose continuation + * keeps every member's tail viable, so nested adaptive simulations + * inside the shared invocation resolve against the real tail decision + * rather than against one member's (arbitrary) alternative + * continuation. The states are appended to the grammar's ATN before it + * is serialized into the generated parser; they are unreachable from + * any rule start. + */ + private static void addSyntheticContinuationStates( + Grammar g, Map factorPlans) + { + for (PrefixFactorAnalyzer.Plan plan : factorPlans.values()) { + for (PrefixFactorAnalyzer.Group grp : plan.groups) { + int ruleIndex = g.atn.decisionToState.get(plan.decision).ruleIndex; + int sharedRule = grp.prefix.get(grp.prefix.size()-1).id; + org.antlr.v4.runtime.atn.BasicState tail = + new org.antlr.v4.runtime.atn.BasicState(); + tail.ruleIndex = ruleIndex; + g.atn.addState(tail); + for (int alt = grp.alts.nextSetBit(0); alt >= 0; alt = grp.alts.nextSetBit(alt+1)) { + tail.addTransition(new org.antlr.v4.runtime.atn.EpsilonTransition( + g.atn.states.get(grp.tailStartState.get(alt)))); + } + org.antlr.v4.runtime.atn.BasicState invoke = + new org.antlr.v4.runtime.atn.BasicState(); + invoke.ruleIndex = ruleIndex; + g.atn.addState(invoke); + invoke.addTransition(new org.antlr.v4.runtime.atn.RuleTransition( + g.atn.ruleToStartState[sharedRule], sharedRule, tail)); + grp.syntheticTailState = tail.stateNumber; + grp.syntheticInvokeState = invoke.stateNumber; + } + } } // --------------------------------------------------------------------- diff --git a/tool/src/org/antlr/v4/analysis/PrefixFactorAnalyzer.java b/tool/src/org/antlr/v4/analysis/PrefixFactorAnalyzer.java index ad05413789..576bca431e 100644 --- a/tool/src/org/antlr/v4/analysis/PrefixFactorAnalyzer.java +++ b/tool/src/org/antlr/v4/analysis/PrefixFactorAnalyzer.java @@ -100,6 +100,22 @@ public static final class Group { public final Map tailStartState = new HashMap(); /** Per-alternative local tail FIRST (block-end delimited). */ public final Map tailFirst = new HashMap(); + /** + * Synthetic call-site state of the group's shared rule + * invocation, created in the ATN by + * {@link DecisionClassifier#buildTables}: a BasicState with a + * single RuleTransition to the shared rule whose follow state is + * {@link #syntheticTailState}. The generated factored arm sets + * the call-site state to this state, so nested adaptive + * simulations inside the shared invocation pop into a position + * where every member's tail is genuinely viable. + */ + public int syntheticInvokeState = -1; + /** + * Synthetic tail-decision state: a BasicState with an epsilon + * transition to every member's {@link #tailStartState}. + */ + public int syntheticTailState = -1; public Group(List prefix) { this.prefix = prefix; } diff --git a/tool/src/org/antlr/v4/codegen/OutputModelController.java b/tool/src/org/antlr/v4/codegen/OutputModelController.java index 5674d8936c..c17c697c44 100644 --- a/tool/src/org/antlr/v4/codegen/OutputModelController.java +++ b/tool/src/org/antlr/v4/codegen/OutputModelController.java @@ -249,6 +249,185 @@ else if (altInfo.isListLabel) { CodeBlockForAlt alt = opAltsCode.get(i); alt.insertOp(0, altAction); } + + // Alt-mask factoring ("implied left-factoring"): when the primary + // block's decision has a validated prefix-factor plan, replace the + // choice with a FactoredAltBlock whose group arms execute the + // shared prefix and resolve the choice with an LL(1) tail switch. + if (primaryStuff instanceof AltBlock) { + org.antlr.v4.tool.Grammar gg = getGrammar(); + org.antlr.v4.analysis.PrefixFactorAnalyzer.Plan factorPlan = + gg.staticFactorPlans != null + ? gg.staticFactorPlans.get(((AltBlock)primaryStuff).decision) : null; + if (factorPlan != null) { + org.antlr.v4.codegen.model.FactoredAltBlock factored = + buildFactoredAltBlock(r, (AltBlock)primaryStuff, factorPlan); + if (factored != null) outerAlt.ops.set(0, factored); + if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FACTOR-CODEGEN rule=%s decision=%d groups=%d built=%s%n", + r.name, ((AltBlock)primaryStuff).decision, factorPlan.groups.size(), + factored != null); + } + } + } + } + + /** + * Build the {@link org.antlr.v4.codegen.model.FactoredAltBlock} for a + * left-recursive rule's primary block from its factor plan, or null + * when model-level validation fails (the ordinary DFAAltBlock then + * stays; mask-accept states in its table defer to adaptivePredict). + * Runs after the label-context specialization actions have been + * inserted in front of the primary alternatives, so each factored + * tail arm can reuse its member's action op. + */ + protected org.antlr.v4.codegen.model.FactoredAltBlock buildFactoredAltBlock( + LeftRecursiveRule r, + AltBlock primaryBlock, + org.antlr.v4.analysis.PrefixFactorAnalyzer.Plan plan) + { + org.antlr.v4.codegen.model.FactoredAltBlock factored = + new org.antlr.v4.codegen.model.FactoredAltBlock(primaryBlock); + for (org.antlr.v4.analysis.PrefixFactorAnalyzer.Group grp : plan.groups) { + int[] members = new int[Long.bitCount(altBitsOf(grp))]; + long mask = altBitsOf(grp); + int prefixLen = grp.prefix.size(); + // per-member structure: context action (labeled alts), prefix, tail + java.util.List tailBodies = new java.util.ArrayList(); + CodeBlockForAlt prefixBody = null; + boolean valid = true; + int m = 0; + for (int alt = grp.alts.nextSetBit(0); alt >= 0 && valid; alt = grp.alts.nextSetBit(alt+1)) { + if (alt < 1 || alt > primaryBlock.alts.size() + || alt > r.recPrimaryAlts.size()) { valid = false; break; } + CodeBlockForAlt altBody = primaryBlock.alts.get(alt-1); + boolean hasCtxAction = r.recPrimaryAlts.get(alt-1).altLabel != null; + int skip = hasCtxAction ? 1 : 0; + // The ops list carries inert null placeholders between + // real element ops; the element sequence is the non-null ops. + java.util.List elementOps = new java.util.ArrayList(); + if (altBody.ops != null) { + for (int i = skip; i < altBody.ops.size(); i++) { + SrcOp op = altBody.ops.get(i); + if (op != null) elementOps.add(op); + } + } + if (elementOps.size() < prefixLen + 1) { + if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FACTOR-FAIL alt=%d elementOps=%d need>=%d%n", alt, + elementOps.size(), prefixLen + 1); + } + valid = false; break; + } + java.util.List prefixOps = elementOps.subList(0, prefixLen); + for (SrcOp op : prefixOps) { + if (!isPlainPrefixElement(op)) { + if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FACTOR-FAIL alt=%d op=%s not plain%n", alt, + op.getClass().getSimpleName()); + } + valid = false; break; + } + } + if (!valid) break; + if (prefixBody == null) { + prefixBody = new CodeBlockForAlt(delegate); + java.util.List sharedOps = new java.util.ArrayList(prefixOps); + // The shared rule invocation must push the synthetic + // call-site state (whose continuation spans every + // member's tail), not any one member's - else nested + // adaptive simulations prune against that member's + // continuation (the (-1)-vs-(COL, -1) bug class). + org.antlr.v4.codegen.model.InvokeRule sharedInvoke = + new org.antlr.v4.codegen.model.InvokeRule( + (org.antlr.v4.codegen.ParserFactory)delegate, + ((org.antlr.v4.codegen.model.InvokeRule)prefixOps.get(prefixLen-1)).ast, + null); + sharedInvoke.stateNumber = grp.syntheticInvokeState; + sharedOps.set(prefixLen-1, sharedInvoke); + prefixBody.addOps(sharedOps); + } + else if (!samePrefix(prefixBody.ops, prefixOps)) { + if ("factor".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FACTOR-FAIL alt=%d prefix mismatch%n", alt); + } + valid = false; break; + } + CodeBlockForAlt tailBody = new CodeBlockForAlt(delegate); + if (hasCtxAction) tailBody.addOp(altBody.ops.get(0)); + tailBody.addOps(new java.util.ArrayList(elementOps.subList(prefixLen, elementOps.size()))); + tailBodies.add(tailBody); + members[m++] = alt; + } + if (!valid) return null; + org.antlr.v4.codegen.model.FactoredGroup group = + new org.antlr.v4.codegen.model.FactoredGroup(delegate, mask, prefixBody); + for (int i = 0; i < members.length; i++) { + org.antlr.v4.runtime.misc.IntervalSet first = grp.tailFirst.get(members[i]); + if (first == null || first.isNil()) return null; + group.tails.add(new org.antlr.v4.codegen.model.FactoredTailArm( + delegate, tailArmKey(first), tailBodies.get(i))); + } + factored.groups.add(group); + } + return factored; + } + + /** Group alternative bitmask (bit 1<<(alt-1) per member). */ + private static long altBitsOf(org.antlr.v4.analysis.PrefixFactorAnalyzer.Group grp) { + long bits = 0; + for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { + bits |= 1L << (a-1); + } + return bits; + } + + /** Prefix elements must be plain, unlabeled token matches or rule + * invocations (v1). */ + private static boolean isPlainPrefixElement(SrcOp op) { + if (op instanceof org.antlr.v4.codegen.model.MatchToken) { + return ((org.antlr.v4.codegen.model.MatchToken)op).labels.isEmpty(); + } + if (op instanceof org.antlr.v4.codegen.model.InvokeRule) { + return ((org.antlr.v4.codegen.model.InvokeRule)op).labels.isEmpty(); + } + return false; + } + + private static boolean samePrefixElement(SrcOp a, SrcOp b) { + if (a instanceof org.antlr.v4.codegen.model.MatchToken + && b instanceof org.antlr.v4.codegen.model.MatchToken) { + return ((org.antlr.v4.codegen.model.MatchToken)a).ttype + == ((org.antlr.v4.codegen.model.MatchToken)b).ttype; + } + if (a instanceof org.antlr.v4.codegen.model.InvokeRule + && b instanceof org.antlr.v4.codegen.model.InvokeRule) { + return ((org.antlr.v4.codegen.model.InvokeRule)a).name + .equals(((org.antlr.v4.codegen.model.InvokeRule)b).name); + } + return false; + } + + private static boolean samePrefix(java.util.List a, java.util.List b) { + if (a.size() != b.size()) return false; + for (int i = 0; i < a.size(); i++) { + if (!samePrefixElement(a.get(i), b.get(i))) return false; + } + return true; + } + + /** Match-arm pattern of a tail FIRST set: the grammar's token-type + * constants joined with " | ". */ + private String tailArmKey(org.antlr.v4.runtime.misc.IntervalSet first) { + StringBuilder sb = new StringBuilder(); + org.antlr.v4.codegen.Target target = delegate.getGenerator().getTarget(); + for (int i = 0; i < first.size(); i++) { + if (i > 0) sb.append(" | "); + int ttype = first.get(i); + sb.append(getGrammar().name).append('_') + .append(target.escapeIfNeeded(target.getTokenTypeAsTargetLabel(getGrammar(), ttype))); + } + return sb.toString(); } public void buildNormalRuleFunction(Rule r, RuleFunction function) { diff --git a/tool/src/org/antlr/v4/codegen/model/FactoredAltBlock.java b/tool/src/org/antlr/v4/codegen/model/FactoredAltBlock.java new file mode 100644 index 0000000000..3f498f93cd --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/FactoredAltBlock.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * An alt block whose decision is driven by a statically-precomputed SLL + * prediction table via the mask protocol ("implied left-factoring"): + * the runtime's dfaPredictMask walker returns the set of live + * alternatives as a bitmask. Singleton masks take the ordinary + * alternative arms; a mask covering a prefix-factor group takes its + * factored arm, which executes the group's shared prefix and then + * resolves the choice with the group's LL(1) tail decision. + */ +public class FactoredAltBlock extends AltBlock { + /** One singleton-mask arm: the ordinary full-alternative body, keyed + * by its single-bit alternative mask. */ + public static class SingletonArm extends OutputModelObject { + public final String armKey; + @ModelElement public final CodeBlockForAlt body; + + public SingletonArm(OutputModelFactory factory, int alt, CodeBlockForAlt body) { + super(factory); + this.armKey = "0x" + Long.toHexString(1L << (alt-1)); + this.body = body; + } + } + + @ModelElement public final List singletons = new ArrayList(); + @ModelElement public final List groups = new ArrayList(); + + public FactoredAltBlock(AltBlock base) { + super(base.factory, base.ast, base.alts); + this.decision = base.decision; + this.tableCanDefer = base.tableCanDefer; + this.label = base.label; + this.preamble = base.preamble; + for (int i = 0; i < base.alts.size(); i++) { + singletons.add(new SingletonArm(base.factory, i+1, base.alts.get(i))); + } + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/FactoredGroup.java b/tool/src/org/antlr/v4/codegen/model/FactoredGroup.java new file mode 100644 index 0000000000..5f07f0fa35 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/FactoredGroup.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * One prefix-factor group of a {@link FactoredAltBlock}: the shared + * prefix (executed once, committing to no group member) and one tail + * arm per member alternative, keyed by the tail's FIRST tokens. + */ +public class FactoredGroup extends OutputModelObject { + /** Match-arm key of the group's alternative mask (hex literal). */ + public final String maskKey; + @ModelElement public final CodeBlockForAlt prefix; + @ModelElement public final List tails = new ArrayList(); + + public FactoredGroup(OutputModelFactory factory, long mask, CodeBlockForAlt prefix) { + super(factory); + this.maskKey = "0x" + Long.toHexString(mask); + this.prefix = prefix; + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/FactoredTailArm.java b/tool/src/org/antlr/v4/codegen/model/FactoredTailArm.java new file mode 100644 index 0000000000..9aeda1febb --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/FactoredTailArm.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; + +/** + * One tail arm of a {@link FactoredGroup}: the arm key (token-type + * constants of the member alternative's tail FIRST set, joined for a + * Rust match pattern) and the tail body (the member's label-context + * specialization action, if any, followed by its tail element ops). + */ +public class FactoredTailArm extends OutputModelObject { + /** Match-arm pattern: token-type constants joined with " | ". */ + public final String armKey; + @ModelElement public final CodeBlockForAlt body; + + public FactoredTailArm(OutputModelFactory factory, String armKey, CodeBlockForAlt body) { + super(factory); + this.armKey = armKey; + this.body = body; + } +} diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index 773713905f..64a42e65e6 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -204,6 +204,15 @@ public class Grammar implements AttributeResolver { */ public Map staticPrecedenceDFAs; + /** + * Prefix-factor plans of factorable decisions (see + * {@link org.antlr.v4.analysis.PrefixFactorAnalyzer}), keyed by decision + * number; populated only with -Xstatic-dfa, and only for decisions with + * at least one validated group. Drives the FactoredAltBlock codegen + * ("implied left-factoring"). + */ + public Map staticFactorPlans; + public final Tool tool; /** Token names and literal tokens like "void" are uniquely indexed. From a2623ab11d381087adbf6ffede175a06128d629a Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sun, 19 Jul 2026 16:09:23 -0400 Subject: [PATCH 18/48] Optional-postfix take-rule analysis: dry-run fire/veto measurement OptionalPostfixAnalyzer detects optional-postfix (X Y?) decisions and DecisionClassifier's dry run counts the conflict states where the take rule would fire: skip is never uniquely viable when every skip-side token consumption mirrors into the take structure, so the conflict statically resolves to take. Conditions: optional-postfix shape (2-alt, alt 1 postfix, alt 2 skip), no starvation (a mandatory following element whose FIRST intersects the optional's would let skip serve it - kills TRIM's trimChar? and namedParameter's identifier?), mirror (each descended skip config's deepest context frame is a return into the decision block's end - re-entry through the take path), no foreign consumption, attested real take. Dry run only: no accept changes (checked-in parsers byte-identical). Report: per-decision [postfix: takeFires=N] and a take-rule summary; TAKE-FIRE/TAKE-VETO diagnostics under -Dantlr.dfa.debug=postfix. Coverage: 158 conflict states across the six dialects, all in the pred? family (Trino d=235, Bigquery d=309, Databricks d=382, Duckdb d=337, Redshift d=314, Snowflake d=603) plus joinCriteria dangling else; the BetweenExpr witness decision fires at all 3 of its escapes. The alias family vetoes on mirror (clause continuations let skip win: SELECT a LIMIT 10 / SELECT a FROM T). Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 109 +++++++++++++ .../v4/analysis/OptionalPostfixAnalyzer.java | 149 ++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 tool/src/org/antlr/v4/analysis/OptionalPostfixAnalyzer.java diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 6e74a64940..5f8f2a87c4 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -187,6 +187,11 @@ public static class Result { public int factorMaskStates; /** Dry-run: escape states that a mask accept would cure. */ public int factorEscapesCured; + /** Dry-run: conflict states where the optional-postfix take rule + * fires (mirror + vetoes pass): would accept take (alt 1). */ + public int takeRuleFires; + /** Dry-run: the decision is an optional-postfix (X Y?) shape. */ + public boolean hasPostfixShape; public Result(DecisionState decisionState) { this.decisionState = decisionState; @@ -451,15 +456,21 @@ public Result(DecisionState decisionState) { /** Analyzer for prefix-factorable decisions (alt-mask dry run). */ protected final PrefixFactorAnalyzer factorAnalyzer; + /** Analyzer for optional-postfix (X Y?) decisions (take-rule dry run). */ + protected final OptionalPostfixAnalyzer postfixAnalyzer; /** Factor plan of the decision under construction; null when the * decision has no groups or is a precedence loop decision. */ protected PrefixFactorAnalyzer.Plan currentFactorPlan; + /** Optional-postfix shape of the decision under construction; null + * when the decision is not an optional-postfix (X Y?) shape. */ + protected OptionalPostfixAnalyzer.Shape currentPostfixShape; public DecisionClassifier(Grammar g) { this.g = g; this.atn = g.atn; this.allTokens = IntervalSet.of(Token.MIN_USER_TOKEN_TYPE, atn.maxTokenType); this.factorAnalyzer = new PrefixFactorAnalyzer(g, atn); + this.postfixAnalyzer = new OptionalPostfixAnalyzer(atn); } /** Classify all decisions of the grammar, indexed by decision number. */ @@ -474,6 +485,7 @@ public List classifyAll() { public Result classify(DecisionState s) { Result res = new Result(s); this.currentFactorPlan = null; + this.currentPostfixShape = null; if (s.nonGreedy) { res.category = Category.NON_GREEDY; return res; @@ -491,6 +503,8 @@ public Result classify(DecisionState s) { // alt-mask dry run: compute the prefix-factor plan up front; the // construction attempts count the states it would resolve. this.currentFactorPlan = factorAnalyzer.analyze(s); + // optional-postfix take-rule dry run + this.currentPostfixShape = postfixAnalyzer.analyze(s); if (currentFactorPlan.hasGroups() && "factor".equals(System.getProperty("antlr.dfa.debug"))) { for (PrefixFactorAnalyzer.Group grp : currentFactorPlan.groups) { @@ -522,10 +536,12 @@ public Result classify(DecisionState s) { Result hybrid = classifyHybrid(s); if (hybrid != null && hybrid.dfa != null) { if (currentFactorPlan.hasGroups()) hybrid.factorPlan = currentFactorPlan; + hybrid.hasPostfixShape = currentPostfixShape != null; return hybrid; } } if (currentFactorPlan.hasGroups()) outcome.factorPlan = currentFactorPlan; + outcome.hasPostfixShape = currentPostfixShape != null; return outcome; } @@ -1144,6 +1160,61 @@ && hasPendingPrecReturn(c.context)) { } } + // Optional-postfix take rule (dry run): the take/skip + // conflict of an X Y? decision is a dangling-else shape. + // When every token the skip reading consumes is mirrored + // into the take structure itself - each descended skip + // configuration's deepest context frame is a return into + // the decision's block end, i.e. the phantom continuation + // funnels back through this decision's own take path, and + // nothing was consumed in a foreign frame - then skip is + // never uniquely viable and the conflict statically + // resolves to take. The mirror check is what excludes the + // alias family, where the clause continuations (LIMIT, + // FROM, ...) let skip genuinely win. Dry run: count only. + if (currentPostfixShape != null + && conflicting.cardinality() == 2 + && conflicting.get(1) && conflicting.get(2)) { + boolean skipForeign = false; + boolean mirrorOk = true; + boolean realTake = false; + for (ATNConfig c : cs) { + if (c.alt == 2) { + if ((c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) != 0) { + skipForeign = true; + } + if (c.state.ruleIndex != s.ruleIndex + && !bottomFrameIs(c.context, + currentPostfixShape.blockEndState, + java.util.Collections.newSetFromMap( + new java.util.IdentityHashMap()))) { + mirrorOk = false; + } + } + if (c.alt == 1 + && (c.reachesIntoOuterContext & (WIDENED_TAINT|FOREIGN_CONSUME_TAINT)) == 0) { + realTake = true; + } + } + if (mirrorOk && !skipForeign && realTake) { + res.takeRuleFires++; + if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("TAKE-FIRE d=%d state=%d exact=%s%n", s.decision, d, exact); + for (ATNConfig c : cs) { + if (c.alt == 2) { + System.err.printf(" skip %s:%d taint=%d ctx=%s%n", + g.getRule(c.state.ruleIndex).name, c.state.stateNumber, + c.reachesIntoOuterContext, decodeContext(c.context)); + } + } + } + } + else if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("TAKE-VETO d=%d state=%d exact=%s foreign=%s mirror=%s realTake=%s%n", + s.decision, d, exact, skipForeign, mirrorOk, realTake); + } + } + // A conflict is trusted as an exact ambiguity only if it is // exact, involves no widened (analysis-only over-approximated) // configs, and its boundary usage is uniform: either the @@ -1798,6 +1869,32 @@ protected boolean isLoopConsumption(ATNConfig c) { * an alternative tail (the operand of a simple operator, after which * the alternative is complete)? */ + /** + * Is every context frame adjacent to the empty context (the deepest + * frame of each context branch) a return into {@code endState}? For + * the optional-postfix mirror check: a skip configuration mirrors + * the take reading iff it re-entered the decision through this + * decision's own take path, i.e. its deepest frame's return state is + * the decision block's end state. A branch that reaches the empty + * context without such a frame means the configuration consumed + * tokens fully outside the decision's discipline (foreign). + */ + private boolean bottomFrameIs(PredictionContext ctx, int endState, + Set visited) { + if (ctx == null || ctx.isEmpty()) return false; + if (!visited.add(ctx)) return true; + for (int i = 0; i < ctx.size(); i++) { + PredictionContext p = ctx.getParent(i); + if (p == null || p.isEmpty()) { + if (ctx.getReturnState(i) != endState) return false; + } + else if (!bottomFrameIs(p, endState, visited)) { + return false; + } + } + return true; + } + private boolean hasPendingPrecReturn(PredictionContext ctx) { if (ctx == null || ctx.isEmpty()) return false; for (int i = 0; i < ctx.size(); i++) { @@ -2154,6 +2251,15 @@ else if (r.dfa == null) { "factorable: %d decisions (%d groups); mask-accepts=%d states; escapes curable=%d%n", factorDecisions, factorGroups, factorMaskStates, factorCured)); } + int postfixDecisions = 0, takeFires = 0; + for (Result r : results) { + if (r.hasPostfixShape) postfixDecisions++; + takeFires += r.takeRuleFires; + } + if (postfixDecisions > 0) { + buf.append(String.format("take-rule: %d optional-postfix decisions; fires at %d conflict states%n", + postfixDecisions, takeFires)); + } int maxKAnyAcyclic = 0; int maxKLLK = 0; @@ -2206,6 +2312,9 @@ else if (r.dfa == null) { .append(" cures=").append(r.factorEscapesCured) .append(']'); } + if (r.hasPostfixShape) { + buf.append(" [postfix: takeFires=").append(r.takeRuleFires).append(']'); + } buf.append('\n'); } buf.append("LLK k histogram: ").append(llkHistogram).append('\n'); diff --git a/tool/src/org/antlr/v4/analysis/OptionalPostfixAnalyzer.java b/tool/src/org/antlr/v4/analysis/OptionalPostfixAnalyzer.java new file mode 100644 index 0000000000..9ee3be2952 --- /dev/null +++ b/tool/src/org/antlr/v4/analysis/OptionalPostfixAnalyzer.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.analysis; + +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNState; +import org.antlr.v4.runtime.atn.BlockStartState; +import org.antlr.v4.runtime.atn.DecisionState; +import org.antlr.v4.runtime.atn.RuleTransition; +import org.antlr.v4.runtime.atn.Transition; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashSet; +import java.util.Set; + +/** + * Detects optional-postfix decisions: two-alternative block + * decisions of the shape {@code X Y?} - alternative 1 ("take") enters a + * postfix (a rule invocation, possibly nested inside a compound block), + * alternative 2 ("skip") is an epsilon path straight to the block end. + * The {@code pred=predicate?} decision of the SQL dialects' + * booleanExpression is the canonical example; {@code (AS? alias)?} is + * the canonical compound shape. + * + *

Such a decision's take/skip conflict is a dangling-else shape: + * whenever every token the skip reading consumes is mirrored into the + * take structure itself (the phantom continuation funnels back through + * this decision's own take path), skip is never uniquely viable and the + * conflict statically resolves to take. See DecisionClassifier's + * optional-postfix take rule.

+ */ +public class OptionalPostfixAnalyzer { + + /** The detected optional-postfix shape of one decision. */ + public static final class Shape { + public final int decision; + /** State number of the decision block's end state: the position + * the take reading reaches when the postfix completes. The + * mirror check requires every descended skip configuration's + * deepest context frame to be a return into this state (i.e. + * the skip re-entered through this decision's own take path). */ + public final int blockEndState; + /** Rule index of the postfix rule when alternative 1 begins with + * a plain rule invocation; -1 for compound postfix blocks. */ + public final int postfixRule; + public final boolean compound; + + public Shape(int decision, int blockEndState, int postfixRule, boolean compound) { + this.decision = decision; + this.blockEndState = blockEndState; + this.postfixRule = postfixRule; + this.compound = compound; + } + } + + private final ATN atn; + + public OptionalPostfixAnalyzer(ATN atn) { this.atn = atn; } + + /** The optional-postfix shape of the decision, or null. */ + public Shape analyze(DecisionState ds) { + if (!(ds instanceof BlockStartState)) return null; + if (ds.getNumberOfTransitions() != 2) return null; + BlockStartState block = (BlockStartState)ds; + + // Alternative 2 must skip: an epsilon-only path to the block end. + if (!epsilonPathTo(ds.transition(1).target, block.endState, new HashSet())) { + return null; + } + + // Alternative 1 must head into a postfix. Walk epsilon links to + // the first non-epsilon element. + ATNState first = firstElement(ds.transition(0).target); + if (first == null) return null; + boolean compound = true; + int postfixRule = -1; + for (int i = 0; i < first.getNumberOfTransitions(); i++) { + Transition t = first.transition(i); + if (t instanceof RuleTransition) { + postfixRule = ((RuleTransition)t).ruleIndex; + compound = false; + break; + } + } + if (postfixRule < 0 && !(first instanceof BlockStartState)) return null; + + // Starvation check: if a mandatory element follows the optional + // and its FIRST set intersects the optional's, the skipped input + // can serve that element instead - skip genuinely wins there + // (TRIM(x), IN foo), so the take rule must not apply. Safe when + // the rest of the alternative can complete token-free (the + // optional is effectively last, as in pred=predicate?). + ATNState ruleStop = null; + for (ATNState st : atn.states) { + if (st != null && st.ruleIndex == ds.ruleIndex + && st instanceof org.antlr.v4.runtime.atn.RuleStopState) { + ruleStop = st; + break; + } + } + org.antlr.v4.runtime.atn.LL1Analyzer ll1 = new org.antlr.v4.runtime.atn.LL1Analyzer(atn); + org.antlr.v4.runtime.misc.IntervalSet contFirst = + ll1.LOOK(block.endState, ruleStop, null); + if (!contFirst.contains(org.antlr.v4.runtime.Token.EPSILON)) { + org.antlr.v4.runtime.misc.IntervalSet takeFirst = + ll1.LOOK(ds.transition(0).target, block.endState, null); + takeFirst.remove(org.antlr.v4.runtime.Token.EPSILON); + if (contFirst.and(takeFirst).size() > 0) return null; + } + + return new Shape(ds.decision, block.endState.stateNumber, postfixRule, compound); + } + + private boolean epsilonPathTo(ATNState from, ATNState to, Set visited) { + if (from == to) return true; + if (!visited.add(from.stateNumber)) return false; + for (int i = 0; i < from.getNumberOfTransitions(); i++) { + Transition t = from.transition(i); + if (t.isEpsilon() && epsilonPathTo(t.target, to, visited)) return true; + } + return false; + } + + /** First state with a non-epsilon outgoing transition reachable by + * epsilon links; null when none is found (empty alternative). + * NB: RuleTransition.isEpsilon() is true - it must be treated as an + * element, not an epsilon link to follow. */ + private ATNState firstElement(ATNState start) { + Deque work = new ArrayDeque(); + Set visited = new HashSet(); + work.add(start); + while (!work.isEmpty()) { + ATNState s = work.remove(); + if (!visited.add(s.stateNumber)) continue; + for (int i = 0; i < s.getNumberOfTransitions(); i++) { + Transition t = s.transition(i); + if (t instanceof RuleTransition) return s; + if (!t.isEpsilon()) return s; + work.add(t.target); + } + } + return null; + } +} From 712d37c2b9c391fac56ee893f1be900696777894 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Mon, 20 Jul 2026 02:20:04 -0400 Subject: [PATCH 19/48] FactoredAltBlock: gate factored codegen on target capability; serializable synthetic tail decision state Two Java-compatibility fixes for the alt-mask machinery. First, the controller's factored-block replacement now runs only for targets with mask codegen (new Target.supportsFactoredAltMask, true for Rust); other targets keep the ordinary DFAAltBlock, whose table's mask-accept states defer to adaptivePredict - Java generation on factorable grammars (Trino d=316) was failing with 'missing code generation template FactoredAltBlock' since the factored work landed. Second, the synthetic tail-decision state appended to the ATN for each factor group is now a BasicBlockStartState (with a paired BlockEndState and a defined decision) instead of a BasicState: it fans out epsilon-wise to every group member's tail start, and the runtime ATN verifier (ATNDeserializer.verifyATN) rejects non-decision states with more than one transition. The Rust deserializer accepted the old form; the Java one did not. Signed-off-by: Bo Lin --- runtime/Rust/tests/gen/parenexprparser.rs | 32 +++++++++---------- .../antlr/v4/analysis/DecisionClassifier.java | 15 +++++++-- .../v4/codegen/OutputModelController.java | 5 ++- tool/src/org/antlr/v4/codegen/Target.java | 9 ++++++ .../antlr/v4/codegen/target/RustTarget.java | 3 ++ 5 files changed, 45 insertions(+), 19 deletions(-) diff --git a/runtime/Rust/tests/gen/parenexprparser.rs b/runtime/Rust/tests/gen/parenexprparser.rs index f249bc8e95..39a34f0749 100644 --- a/runtime/Rust/tests/gen/parenexprparser.rs +++ b/runtime/Rust/tests/gen/parenexprparser.rs @@ -1282,7 +1282,7 @@ where recog.base.set_state(12); recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; /*InvokeRule e*/ - recog.base.set_state(56); + recog.base.set_state(57); recog.e_rec(0)?; } match recog.input.la(1) { @@ -1873,20 +1873,20 @@ static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| A static _ATN: LazyLock = LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); static _serializedATN: [&'static str; 16] = [ - "CAIWcgQADgAEAg4CBAQOBAIAAgACAAICAgICAgICAgICAgICCAIiEAIWAhgCJAICAgICAgICAgICAgIC", + "CAIWdAQADgAEAg4CBAQOBAIAAgACAAICAgICAgICAgICAgICCAIiEAIWAhgCJAICAgICAgICAgICAgIC", "AgICAgICAgICAgYCQhACAgICAgICAgICAgICCgJSEAIUAhgCWBICAgQCBAIEAgQCBAIEAgQGBGoQBAIE", - "AgICAgACBAYABAgABAIACgwEAAgIDg6AAQAMAgAAAARAAgAAAAhoAgAAAAwOBgQCAA4QCgAAAhACAgAA", - "ABIUDAIBABRCChQAABZCChIAABgaCgIAABogBgQCABweCgQAAB4iBgQCACAcAgAAACIkAgAAACQgAgAA", - "ACQmAgAAACYoAgAAACgqCgYAACpCAgAAACwuCgIAAC4wBgQCADAyCgYAADJCAgAAADQ2CgIAADY4BggE", - "ADg6CgYAADpCAgAAADw+CggAAD5CBgQCBkASAgAAAEAWAgAAAEAYAgAAAEAsAgAAAEA0AgAAAEA8AgAA", - "AEJUAgAAAERGFAQAAEZIDgAAAEhSBgQCBkpMFAIAAExODgIAAE5SBgQCBFBEAgAAAFBKAgAAAFJYAgAA", - "AFRQAgAAAFRWAgAAAFYGAgAAAFhUAgAAAFpcChAAAFxqChIAAF5qChIAAGBiCgIAAGJkBggEAGRmCgYA", - "AGZqAgAAAGhaAgAAAGheAgAAAGhgAgAAAGoKAgAAAG4gAgAAAG4wAgAAAHBuBgQCAAokQFBUaAwKCAJE", - "9gEAAAwEAgAACgAAAQAAAAAAAAYBAAgAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "AAAAAAAAAAAAAAAYNjY2NlRmZniKAYoBnAGiAbQBxgHkAeQB5AHkAfYB9gH2AfYB9gH2AfYB9gH2AfYB", - "9gH2AfYB9gH2AQICAggIBBISBhQUCAICCggIDBAQDhISEBQUEgICFAgIFhAQGBISGhQUHAICHggIIBIU", - "EgQEIgYGJAgOJgQEIgYGKAgOJgICKggIIBIUHBISLAQELgYGMAgOMgQELgYGNAgOMgICNggIIBAQOBIS", - "OhQUPAICPggIQBIUQhggBAYIKgQGCC4EBggyBAYINAQGCDYEBgg4BAYIOgQGCDwEBgg+BAYIQAQGCEIE", - "BggEBhIABAIAAAAAEhISCAgCCgwEDg4CAAEKGAAEBAQCBAAAAAAAGBgYGBgBAQIEBAQGBgYIDggAAQwk", - "AAQEBAQCBAAAAAAAACQkJCQkJAEBAgQEBAYGBggICAoMCg4OCAABAgAEAAAAAAIGBAIEBAYI" + "BgJwEAICAgACBAYABAgABAIACgwEAAgIDg6AAQAMAgAAAARAAgAAAAhoAgAAAAwOBgQCAA4QCgAAAhAC", + "AgAAABIUDAIBABRCChQAABZCChIAABgaCgIAABogBgQCABweCgQAAB4iBgQCACAcAgAAACIkAgAAACQg", + "AgAAACQmAgAAACYoAgAAACgqCgYAACpCAgAAACwuCgIAAC4wBgQCADAyCgYAADJCAgAAADQ2CgIAADY4", + "BggEADg6CgYAADpCAgAAADw+CggAAD5CBgQCBkASAgAAAEAWAgAAAEAYAgAAAEAsAgAAAEA0AgAAAEA8", + "AgAAAEJUAgAAAERGFAQAAEZIDgAAAEhSBgQCBkpMFAIAAExODgIAAE5SBgQCBFBEAgAAAFBKAgAAAFJY", + "AgAAAFRQAgAAAFRWAgAAAFYGAgAAAFhUAgAAAFpcChAAAFxqChIAAF5qChIAAGBiCgIAAGJkBggEAGRm", + "CgYAAGZqAgAAAGhaAgAAAGheAgAAAGhgAgAAAGoKAgAAAG4gAgAAAG4wAgAAAHJuBgQCAAwkQFBUaG4M", + "CggCRPYBAAAMBAIAAAoAAAEAAAAAAAAGAQAIAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "AAAAAAAAAAAAAAAAAAAAGDY2NjZUZmZ4igGKAZwBogG0AcYB5AHkAeQB5AH2AfYB9gH2AfYB9gH2AfYB", + "9gH2AfYB9gH2AfYB9gECAgIICAQSEgYUFAgCAgoICAwQEA4SEhAUFBICAhQICBYQEBgSEhoUFBwCAh4I", + "CCASFBIEBCIGBiQIDiYEBCIGBigIDiYCAioICCASFBwSEiwEBC4GBjAIDjIEBC4GBjQIDjICAjYICCAQ", + "EDgSEjoUFDwCAj4ICEASFEIYIAQGCCoEBgguBAYIMgQGCDQEBgg2BAYIOAQGCDoEBgg8BAYIPgQGCEAE", + "BghCBAYIBAYSAAQCAAAAABISEggIAgoMBA4OAgABChgABAQEAgQAAAAAABgYGBgYAQECBAQEBgYGCA4I", + "AAEMJAAEBAQEAgQAAAAAAAAkJCQkJCQBAQIEBAQGBgYICAgKDAoODggAAQIABAAAAAACBgQCBAQGCA==" ]; \ No newline at end of file diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 5f8f2a87c4..18f27b4ed7 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -2149,10 +2149,21 @@ private static void addSyntheticContinuationStates( for (PrefixFactorAnalyzer.Group grp : plan.groups) { int ruleIndex = g.atn.decisionToState.get(plan.decision).ruleIndex; int sharedRule = grp.prefix.get(grp.prefix.size()-1).id; - org.antlr.v4.runtime.atn.BasicState tail = - new org.antlr.v4.runtime.atn.BasicState(); + // The tail state fans out (epsilon) to every member's tail + // start, so it must be a real decision state: non-decision + // states may only have one transition (ATNDeserializer's + // verifyATN). It never serves as a prediction call site. + org.antlr.v4.runtime.atn.BasicBlockStartState tail = + new org.antlr.v4.runtime.atn.BasicBlockStartState(); tail.ruleIndex = ruleIndex; g.atn.addState(tail); + org.antlr.v4.runtime.atn.BlockEndState tailEnd = + new org.antlr.v4.runtime.atn.BlockEndState(); + tailEnd.ruleIndex = ruleIndex; + g.atn.addState(tailEnd); + tail.endState = tailEnd; + tailEnd.startState = tail; + g.atn.defineDecisionState(tail); for (int alt = grp.alts.nextSetBit(0); alt >= 0; alt = grp.alts.nextSetBit(alt+1)) { tail.addTransition(new org.antlr.v4.runtime.atn.EpsilonTransition( g.atn.states.get(grp.tailStartState.get(alt)))); diff --git a/tool/src/org/antlr/v4/codegen/OutputModelController.java b/tool/src/org/antlr/v4/codegen/OutputModelController.java index c17c697c44..4b42d2b690 100644 --- a/tool/src/org/antlr/v4/codegen/OutputModelController.java +++ b/tool/src/org/antlr/v4/codegen/OutputModelController.java @@ -254,7 +254,10 @@ else if (altInfo.isListLabel) { // block's decision has a validated prefix-factor plan, replace the // choice with a FactoredAltBlock whose group arms execute the // shared prefix and resolve the choice with an LL(1) tail switch. - if (primaryStuff instanceof AltBlock) { + // Only for targets with mask codegen; others keep the DFAAltBlock + // (mask-accept states in its table defer to adaptivePredict). + if (primaryStuff instanceof AltBlock + && delegate.getGenerator().getTarget().supportsFactoredAltMask()) { org.antlr.v4.tool.Grammar gg = getGrammar(); org.antlr.v4.analysis.PrefixFactorAnalyzer.Plan factorPlan = gg.staticFactorPlans != null diff --git a/tool/src/org/antlr/v4/codegen/Target.java b/tool/src/org/antlr/v4/codegen/Target.java index c2324dd05a..563379591b 100644 --- a/tool/src/org/antlr/v4/codegen/Target.java +++ b/tool/src/org/antlr/v4/codegen/Target.java @@ -666,6 +666,15 @@ public boolean isATNSerializedAsInts() { */ public boolean supportsStaticDFA() { return false; } + /** + * Whether this target implements factored alt-mask prediction + * ("implied left-factoring"): the FactoredAltBlock template and a + * dfaPredictMask runtime helper. Targets without it keep the ordinary + * DFAAltBlock for prefix-factorable decisions (mask-accept states in + * the table defer to adaptivePredict, as escapes do). + */ + public boolean supportsFactoredAltMask() { return false; } + /** * Whether this target's serialized ATN is emitted as a compact * base64/varint blob (see {@link org.antlr.v4.codegen.CompactSerializer}) diff --git a/tool/src/org/antlr/v4/codegen/target/RustTarget.java b/tool/src/org/antlr/v4/codegen/target/RustTarget.java index bcfab8af12..6beba49bc8 100644 --- a/tool/src/org/antlr/v4/codegen/target/RustTarget.java +++ b/tool/src/org/antlr/v4/codegen/target/RustTarget.java @@ -98,6 +98,9 @@ public int getInlineTestSetWordSize() { @Override public boolean supportsStaticDFA() { return true; } + @Override + public boolean supportsFactoredAltMask() { return true; } + @Override public boolean isATNSerializedAsBase64VarInts() { return true; } } From d31f693a68caba837f5d47b2803b17351db5ee59 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Mon, 20 Jul 2026 02:20:31 -0400 Subject: [PATCH 20/48] Optional-postfix take rule: dangling-else resolution for X Y? decisions The take/skip conflict of an optional-postfix decision (pred? in booleanExpression, joinCriteria? in joinedRelation) is a dangling-else shape: when every token the skip reading consumes is mirrored into the take structure itself (each descended skip configuration's deepest context frame is a return into the decision's block end, nothing was consumed in a foreign frame, and take viability is attested by a non-widened, non-foreign config), skip is never uniquely viable, so the conflict statically resolves to take (alt 1). The starvation check in the analyzer excludes X Y? Z shapes where a mandatory Z can be served by the skipped input (TRIM trimChar, namedParameter identifier); the mirror check excludes the alias family, whose clause continuations (LIMIT, FROM, ...) let skip genuinely win - those stay escaped, as do the context-free divergences between the two. Fires at 158 conflict states across the seven SQL dialects, all in the pred? family plus the joinCriteria dangling-else; BetweenExpr's witness decision goes fully static (fb=3 -> 0) with all pinned corners green. Verified: the original user query is now fully static on Trino; alias and TRIM witnesses parse identically to adaptive; 312-query pred-family corpus and the 1690+1200+10 corpora are static/adaptive identical; cargo (11 suites) and runtime-testsuite rust.** (707 tests) green; escape counts drop in every dialect (Duckdb -56, Redshift -48, Databricks -40, Snowflake -32, Bigquery -19, Trino -6). Signed-off-by: Bo Lin --- runtime/Rust/tests/gen/betweenexprparser.rs | 6 +-- .../antlr/v4/analysis/DecisionClassifier.java | 38 ++++++++++++------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index 8b7cd0dd8a..698cf57c0c 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -854,7 +854,7 @@ where recog.v_rec(0)?; recog.base.set_state(16); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(0)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(0,&mut recog.base)? } else { _sdp } } { + match { let _sdp = recog.base.dfa_predict(0)?; _sdp } { x if x == 1 =>{ { /*InvokeRule pred*/ @@ -1673,7 +1673,7 @@ where // the serialized ATN is followed by 9 static SLL prediction tables (-Xstatic-dfa): // decision 3: precedence-dispatched over cutoffs [1, 2], tables [4 5 6] // decision 7: precedence-dispatched over cutoffs [2, 3], tables [7 8 6] -// decision 0: LL(k), k=1, 9 states, 3 adaptive escapes +// decision 0: LL(k), k=1, 9 states // decision 2: LL(k), k=1, 3 states // decision 6: LL(k), k=1, 3 states // decision 8: LL(k), k=2, 13 states @@ -1697,7 +1697,7 @@ static _serializedATN: [&'static str; 19] = [ "FAYAAGJkDgIAAGRuBgwGCGZoFAQAAGhqDgQAAGpuBgwGBmxgAgAAAGxmAgAAAG50AgAAAHBsAgAAAHBy", "AgAAAHIOAgAAAHRwAgAAAHaKAQoeAAB4igEKIAAAenwKGAAAfH4GBAIAfoABChoAAIABigECAAAAggGE", "AQoeAACEAYYBChwAAIYBigEGBAIAiAF2AgAAAIgBeAIAAACIAXoCAAAAiAGCAQIAAACKARICAAAAEiAo", - "ODxEVmxwiAEMEhIAEjAABAEEBAEBBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", + "ODxEVmxwiAEMEhIAEjAABAIEBAICBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", "EBYOGhoQAAQGDAACBAAAAAAMDAwEBAIGBgQADAYMAAIEAAAAAAwMDBASAhQWBAAQGkgABgAEAgICAgIC", "AgIIAAACAAAAAAAAAAAAAAASEkhISEhISEhISEhIGBgCHh4EICAGAQEIAgIKBAQMBgYOCAgQCg4SEBYU", "GhoWHBwYAAESMAAEBAECBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4a", diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 18f27b4ed7..5bb35ef4e6 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -281,8 +281,8 @@ public Result(DecisionState decisionState) { * queue is FIFO, so construction is breadth-first by lookahead depth * and the emitted prefix is exactly the shallowest - hottest - states. */ - public int hybridDepthCap = 4; - public int hybridStateCap = 64; + public int hybridDepthCap = Integer.parseInt(System.getProperty("antlr.dfa.hybridDepthCap", "4")); + public int hybridStateCap = Integer.parseInt(System.getProperty("antlr.dfa.hybridStateCap", "64")); /** * Minimum start-state coverage (see {@link Result#coverage}) for a * hybrid table to be worth its size: below this, nearly every @@ -1160,18 +1160,25 @@ && hasPendingPrecReturn(c.context)) { } } - // Optional-postfix take rule (dry run): the take/skip - // conflict of an X Y? decision is a dangling-else shape. - // When every token the skip reading consumes is mirrored - // into the take structure itself - each descended skip - // configuration's deepest context frame is a return into - // the decision's block end, i.e. the phantom continuation - // funnels back through this decision's own take path, and - // nothing was consumed in a foreign frame - then skip is - // never uniquely viable and the conflict statically - // resolves to take. The mirror check is what excludes the - // alias family, where the clause continuations (LIMIT, - // FROM, ...) let skip genuinely win. Dry run: count only. + // Optional-postfix take rule: the take/skip conflict of an + // X Y? decision is a dangling-else shape. When every token + // the skip reading consumes is mirrored into the take + // structure itself - each descended skip configuration's + // deepest context frame is a return into the decision's + // block end (the phantom continuation funnels back through + // this decision's own take path), nothing was consumed in + // a foreign frame, and take viability is attested by a + // non-widened, non-foreign config - then skip is never + // uniquely viable: take's continuation after the optional + // is identical to skip's (both reach the same block end), + // and the mirrored re-descents consume the same tokens, so + // whenever the adaptive engine terminates - unique take, + // or an ambiguity resolved to the minimum alternative - + // it answers take. The starvation check (in the analyzer) + // excludes X Y? Z shapes where a mandatory Z can be served + // by the skipped input (TRIM, namedParameter); the mirror + // check excludes the alias family, whose clause + // continuations (LIMIT, FROM, ...) let skip genuinely win. if (currentPostfixShape != null && conflicting.cardinality() == 2 && conflicting.get(1) && conflicting.get(2)) { @@ -1198,6 +1205,8 @@ && hasPendingPrecReturn(c.context)) { } if (mirrorOk && !skipForeign && realTake) { res.takeRuleFires++; + res.exactAmbigConflicts.add(conflicting); + acceptAlts.set(d, 1); if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { System.err.printf("TAKE-FIRE d=%d state=%d exact=%s%n", s.decision, d, exact); for (ATNConfig c : cs) { @@ -1208,6 +1217,7 @@ && hasPendingPrecReturn(c.context)) { } } } + continue; } else if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { System.err.printf("TAKE-VETO d=%d state=%d exact=%s foreign=%s mirror=%s realTake=%s%n", From 33cf3d78b6da91a7eaa3811c286cbfba26879393 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Mon, 20 Jul 2026 15:07:53 -0400 Subject: [PATCH 21/48] Widening instrumentation: guard-reachability census for closure widening events Debug-only (-Dantlr.dfa.debug=widening), zero-cost when off: counts the closure's context-widening events per decision and classifies each by whether the widened call is guard-reachable - dominated by a precedence-guard head of its alternative in the left-recursion transform's shape (epsilon head walk to the guard, then domination up to the alternative's own block end, crossing tokens, not descending into callees). Motivation: sizing a proposed precedence-bounded wildcard root for widened contexts. The measurement answered it in the negative: only ~5-11% of widening events are guard-reachable (ExprLoops 5/170, Trino 12983/120869); the dominant source is the unguarded operand-descent cycle (valueExpression -> primaryExpression -> '(' expression ')' -> expression -> booleanExpression -> ...), on which no static precedence constraint exists. Kept as analysis tooling; no accept logic, table output unchanged. Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 5bb35ef4e6..d80a45f732 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -11,6 +11,8 @@ import org.antlr.v4.runtime.atn.ATNConfig; import org.antlr.v4.runtime.atn.ATNConfigSet; import org.antlr.v4.runtime.atn.ATNState; +import org.antlr.v4.runtime.atn.BlockEndState; +import org.antlr.v4.runtime.atn.BlockStartState; import org.antlr.v4.runtime.atn.DecisionState; import org.antlr.v4.runtime.atn.EmptyPredictionContext; import org.antlr.v4.runtime.atn.LoopEndState; @@ -454,6 +456,23 @@ public Result(DecisionState decisionState) { */ protected Map callByFollowState; + /** + * Lazily built map from a rule-call follow state to the minimum + * precedence-guard threshold that reaches the call over epsilon-only + * paths of the same rule (the left-recursion transform places the + * {@code {n >= _p}?} guard at the head of each operator alternative, + * so it reaches the alternative's recursive operand call). Absent + * entry = the call is not guard-reachable - plain or mutual + * recursion outside the operator-loop discipline. Used by the + * widening instrumentation ({@code -Dantlr.dfa.debug=widening}). + */ + protected Map guardByFollowState; + + /** Widening events in the current construction (debug counter). */ + protected int widenEvents; + /** ...of which the widened call is guard-reachable (debug counter). */ + protected int widenGuarded; + /** Analyzer for prefix-factorable decisions (alt-mask dry run). */ protected final PrefixFactorAnalyzer factorAnalyzer; /** Analyzer for optional-postfix (X Y?) decisions (take-rule dry run). */ @@ -865,6 +884,68 @@ protected Map callByFollowState() { return callByFollowState; } + /** Lazily built {@link #guardByFollowState}. */ + protected Map guardByFollowState() { + if (guardByFollowState == null) { + guardByFollowState = new HashMap(); + for (ATNState bs0 : atn.states) { + if (!(bs0 instanceof BlockStartState)) continue; + BlockStartState bs = (BlockStartState)bs0; + for (int i = 0; i < bs.getNumberOfTransitions(); i++) { + // An operator alternative of the left-recursion + // transform opens with the {n >= _p}? guard; find it + // by an epsilon-only walk of the alternative head + // (stopping at tokens, calls and block ends). + Integer headGuard = null; + Deque head = new ArrayDeque(); + Set headSeen = new HashSet(); + head.add(bs.transition(i).target); + while (!head.isEmpty() && headGuard == null) { + ATNState s = head.poll(); + if (!headSeen.add(s) || s instanceof BlockEndState) continue; + for (int j = 0; j < s.getNumberOfTransitions(); j++) { + Transition t = s.transition(j); + if (t instanceof PrecedencePredicateTransition) { + headGuard = ((PrecedencePredicateTransition)t).precedence; + // mark everything dominated by the guard, + // below + } + else if (t.isEpsilon() && !(t instanceof RuleTransition)) { + head.add(t.target); + } + } + } + if (headGuard == null) continue; + // Everything reachable from the guard without passing + // the alternative's own block end is dominated by it: + // cross tokens, record (do not descend into) calls, + // pass through interior blocks' ends, stop at ours. + int n = headGuard; + Deque work = new ArrayDeque(); + Set seen = new HashSet(); + work.add(bs.transition(i).target); + while (!work.isEmpty()) { + ATNState s = work.poll(); + if (!seen.add(s) || s.ruleIndex != bs.ruleIndex) continue; + if (s == bs.endState || s instanceof RuleStopState) continue; + for (int j = 0; j < s.getNumberOfTransitions(); j++) { + Transition t = s.transition(j); + if (t instanceof RuleTransition) { + int f = ((RuleTransition)t).followState.stateNumber; + Integer prev = guardByFollowState.get(f); + if (prev == null || n < prev) guardByFollowState.put(f, n); + } + else { + work.add(t.target); + } + } + } + } + } + } + return guardByFollowState; + } + /** * Evaluate a precedence guard {@code precpred(n)} of rule {@code rule} * against the precedence the rule was entered with in this closure @@ -983,6 +1064,8 @@ protected Set applyPrecedenceFilter(Set raw) { protected boolean buildDFA(DecisionState s, Result res, int depthBound) { this.currentDepthBound = depthBound; this.currentDecisionNumber = s.decision; + this.widenEvents = 0; + this.widenGuarded = 0; this.depthCache = new java.util.IdentityHashMap(); Map, Integer> stateIds = new HashMap, Integer>(); List> states = new ArrayList>(); @@ -1348,6 +1431,12 @@ else if (abortOnUntrustedConflict) { } } + if (widenEvents > 0 && "widening".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("WIDEN d=%d bound=%s events=%d guarded=%d%n", + s.decision, + depthBound == Integer.MAX_VALUE ? "inf" : String.valueOf(depthBound), + widenEvents, widenGuarded); + } res.numDfaStates = states.size(); if (overflow) { if (System.getProperty("antlr.dfa.debug") != null) { @@ -1768,6 +1857,14 @@ else if (contextDepth(config.context) >= currentDepthBound if (widened) { res.usedWidening = true; callee.reachesIntoOuterContext |= WIDENED_TAINT; + if ("widening".equals(System.getProperty("antlr.dfa.debug"))) { + widenEvents++; + boolean guarded = guardByFollowState().containsKey(followStateNumber); + if (guarded) widenGuarded++; + System.err.printf("WIDEN-EVENT d=%d in=%s call->%s follow=%d guarded=%s%n", + currentDecisionNumber, g.getRule(p.ruleIndex).name, + g.getRule(rt.target.ruleIndex).name, followStateNumber, guarded); + } } closure(callee, configs, busy, res, depth >= 0 ? depth+1 : depth); } From 1aaeb8e97d00aeeeb7d0e066d9a9a3413035a056 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Mon, 20 Jul 2026 18:47:08 -0400 Subject: [PATCH 22/48] Uniform-widening trust: min-alt resolution for conflicts with assured min attestation A conflict in a static-table construction resolves to min(U), the minimum of the conflicting union, when min(U) is the runtime's answer on every real stack. That holds when (a) every (state, ctx) entry of the conflict has min(U) assured: a same-state min(U) configuration whose derivation is tail-independent - runtime-faithful (no widening joint in its context), boundary-pop-free and foreign-consume-free, so it is realizable on every stack matching its context - and whose context covers the entry's, exactly (common-min) or as a wildcard-tailed prefix (shadow); and (b) boundary usage is uniform (all configs popped through the decision boundary, or none), the same fate-equivalence condition the exact-ambiguity trust relies on. Two soundness holes were found and fixed by the witness battery: merged contexts must be covered branch-by-branch (covering only the 16-29-$ branch of [16 29 $, 40 $] misparsed 'x BETWEEN y -> a AND b AND c' in BetweenExpr: a stack arriving via the uncovered branch is matched by the entry but not by the shadow), and mixed boundary usage vetoes (alt 1 boundary-free vs alt 2 boundary-tainted misparsed 'a,c>>x' in LeftRecursion/ReturnValueAndActionsList1_2: the iterate lineage is closure-live but dies in the outer frames at EOF - closure-liveness is not input-viability). Support machinery: widening joints are identity-tracked (SingletonPredictionContext.create allocates per call) so runtime-faithfulness is exact rather than the sticky WIDENED_TAINT over-approximation (which vetoes real resolutions); faithfulness is memoized per attempt. The rule fires in both the full pass and hybrid mode; a full-pass resolution can un-hybridize an entire decision. Results: 21 conflict states resolved across the eight grammars, -837 escape states total (Duckdb -203, Redshift -358, Snowflake -214, Databricks -36, Bigquery -13, Trino -11, ExprLoops -2; BetweenExpr's two escapes correctly retained, as are Send2's). Battery: cargo 11 suites, tool-testsuite 694, runtime-testsuite rust.** 707, 3202-query differential corpus (only the 2 known '::' error-path divergences), 7/7 pinned witnesses, perf unchanged (Trino Q1 2.5us, user query 2.3x vs adaptive). Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 283 ++++++++++++++++-- 1 file changed, 256 insertions(+), 27 deletions(-) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index d80a45f732..9fef0d3f48 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -192,6 +192,9 @@ public static class Result { /** Dry-run: conflict states where the optional-postfix take rule * fires (mirror + vetoes pass): would accept take (alt 1). */ public int takeRuleFires; + /** Conflict states resolved to min(U) by the uniform-widening + * trust (every context entry has an assured min attestation). */ + public int utrustResolutions; /** Dry-run: the decision is an optional-postfix (X Y?) shape. */ public boolean hasPostfixShape; @@ -334,6 +337,21 @@ public Result(DecisionState decisionState) { /** Per-attempt memo for {@link #contextDepth} (contexts share structure). */ protected Map depthCache; + /** + * Identity set (per construction attempt) of the exact context objects + * created by context widening ({@code Singleton(EMPTY, f)} joints). + * {@link SingletonPredictionContext#create} allocates a fresh object + * per call, so the joint created at the widening site is + * distinguishable by identity from any naturally pushed context with + * the same shape. A configuration whose context contains no joint is + * runtime-faithful: its derivation never passed through + * widening (whatever its sticky {@link #WIDENED_TAINT} says - the bit + * is inherited by descendants whose contexts may since have been + * re-established concretely, e.g. by popping below the joint and + * re-pushing real frames). + */ + protected Set widenedJoints; + // -- precedence-decision construction mode (see classifyPrecedence) -- /** @@ -1067,6 +1085,9 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { this.widenEvents = 0; this.widenGuarded = 0; this.depthCache = new java.util.IdentityHashMap(); + this.faithCache = new java.util.IdentityHashMap(); + this.widenedJoints = + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()); Map, Integer> stateIds = new HashMap, Integer>(); List> states = new ArrayList>(); List> edges = new ArrayList>(); @@ -1328,32 +1349,55 @@ else if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { // one class-mode shape where it has). boolean untrusted = widenedTainted || (anyBoundary && !allBoundary) || !trustExactAmbig; - if (untrusted) res.approxConflicts.add(conflicting); - else if (exact) res.exactAmbigConflicts.add(conflicting); - else res.contextSensitiveConflicts.add(conflicting); if (!untrusted && exact) { // trusted exact ambiguity: min-alt resolution matches // both runtime SLL and full-context LL + res.exactAmbigConflicts.add(conflicting); acceptAlts.set(d, conflicting.nextSetBit(0)); } - else if (hybridMode) { - // the conflict cannot be resolved statically: defer - // this state to adaptivePredict - UNLESS its live - // alternatives are covered by one prefix-factor - // group, in which case it accepts with the group's - // alternative mask (the parser resolves the choice - // at the group's tail decision) - if (factorGroup != null) { - res.factorEscapesCured++; - acceptMasks.set(d, altBits(factorGroup.alts)); - } - else { - acceptAlts.set(d, StaticDFA.ESCAPE); + else { + int um = utrustMinAlt(cs, conflicting, anyBoundary, allBoundary); + if (um > 0) { + // uniform-widening trust: min(U) is the runtime's + // answer on every real stack (see utrustMinAlt) + res.utrustResolutions++; + res.exactAmbigConflicts.add(conflicting); + acceptAlts.set(d, um); + if ("utrust".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("UTRUST-RESOLVE d=%d state=%d alt=%d prec=%d%n", + s.decision, d, um, precEvalValue); + for (ATNConfig c : cs) { + System.err.printf(" alt=%d rule=%s state=%d taint=%d faithful=%s ctx=%s%n", + c.alt, g.getRule(c.state.ruleIndex).name, + c.state.stateNumber, c.reachesIntoOuterContext, + runtimeFaithful(c), c.context); + } + } + continue; } - if (System.getProperty("antlr.dfa.debug") != null) { - System.err.printf("ESCAPE-CONFLICT d=%d state=%d depth=%d exact=%s hard=%s anyB=%s allB=%s trustEA=%s alts=%s%n", - s.decision, d, stateDepth.get(d), exact, widenedTainted, - anyBoundary, allBoundary, trustExactAmbig, conflicting); + if (untrusted) res.approxConflicts.add(conflicting); + else res.contextSensitiveConflicts.add(conflicting); + if (hybridMode) { + // the conflict cannot be resolved statically: + // defer this state to adaptivePredict - UNLESS + // its live alternatives are covered by one + // prefix-factor group, in which case it accepts + // with the group's alternative mask (the parser + // resolves the choice at the tail decision) + if (factorGroup != null) { + res.factorEscapesCured++; + acceptMasks.set(d, altBits(factorGroup.alts)); + } + else { + acceptAlts.set(d, StaticDFA.ESCAPE); + } + if ("utrust".equals(System.getProperty("antlr.dfa.debug"))) { + utrustProbe(s, d, cs, conflicting, exact, factorGroup != null, anyBoundary, allBoundary); + } + if (System.getProperty("antlr.dfa.debug") != null) { + System.err.printf("ESCAPE-CONFLICT d=%d state=%d depth=%d exact=%s hard=%s anyB=%s allB=%s trustEA=%s alts=%s%n", + s.decision, d, stateDepth.get(d), exact, widenedTainted, + anyBoundary, allBoundary, trustExactAmbig, conflicting); if ("full".equals(System.getProperty("antlr.dfa.debug"))) { for (ATNConfig c : cs) { System.err.printf(" alt=%d rule=%s state=%d taint=%d ctx=%s%n", @@ -1362,14 +1406,15 @@ else if (hybridMode) { c.context); } } + } + } + else if (abortOnUntrustedConflict) { + // not a trusted exact ambiguity: no widening level + // can make this decision table-eligible + res.numDfaStates = states.size(); + res.category = Category.CONTEXT_SENSITIVE; + return false; } - } - else if (abortOnUntrustedConflict) { - // not a trusted exact ambiguity: no widening level can - // make this decision table-eligible - res.numDfaStates = states.size(); - res.category = Category.CONTEXT_SENSITIVE; - return false; } continue; } @@ -1849,6 +1894,7 @@ else if (contextDepth(config.context) >= currentDepthBound // wildcard context widened = true; newCtx = SingletonPredictionContext.create(EmptyPredictionContext.Instance, followStateNumber); + widenedJoints.add(newCtx); } else { newCtx = SingletonPredictionContext.create(config.context, followStateNumber); @@ -2100,6 +2146,184 @@ protected String decodeContext(PredictionContext ctx) { } /** Does a return state appear anywhere in a (possibly DAG-shaped) context? */ + /** + * Uniform-widening trust probe ({@code -Dantlr.dfa.debug=utrust}): + * classifies an escaping conflict by whether it could resolve to + * min(U), the minimum of the conflicting union, matching the runtime + * on every real stack. + * + *

L1 (common-min): every (state, ctx) entry contains min(U) - + * every real stack's live-alt set contains min(U), so both SLL and + * full-context prediction answer min(U) (unique or min-of-conflict). + * L2 (min-shadowed): an entry lacking min(U) is harmless when a + * min(U) config at the same ATN state carries a widened context that + * is a top-frames prefix of the entry's context with a wildcard tail + * - its real-stack set then contains the entry's, so min(U) is live + * wherever the entry is (soundness still requires the widened config + * to be realizable through the entry's continuation; the probe only + * measures the shape).

+ */ + protected void utrustProbe(DecisionState s, int d, ATNConfigSet cs, BitSet conflicting, + boolean exact, boolean masked, + boolean anyBoundary, boolean allBoundary) { + Map> byStateCtx = groupByStateCtx(cs); + int m = conflicting.nextSetBit(0); + int entries = 0, loneMin = 0; + for (Map.Entry> e1 : byStateCtx.entrySet()) { + for (Map.Entry e2 : e1.getValue().entrySet()) { + entries++; + if (!e2.getValue().get(m)) loneMin++; + } + } + System.err.printf("UTRUST d=%d state=%d exact=%s masked=%s entries=%d union=%s loneMin=%d verdict=%s%n", + s.decision, d, exact, masked, entries, conflicting, loneMin, + utrustMinAlt(cs, conflicting, anyBoundary, allBoundary) > 0 ? "RESOLVABLE" : "no"); + } + + /** Group a configuration set's alternatives by (ATN state, context). */ + private static Map> groupByStateCtx(ATNConfigSet cs) { + Map> byStateCtx = + new LinkedHashMap>(); + for (ATNConfig c : cs) { + BitSet alts = byStateCtx + .computeIfAbsent(c.state.stateNumber, k -> new LinkedHashMap()) + .computeIfAbsent(c.context, k -> new BitSet()); + alts.set(c.alt); + } + return byStateCtx; + } + + /** + * Uniform-widening trust: the minimum of the conflicting union is the + * runtime's answer on every real stack - and may therefore be + * accepted statically - when every (state, ctx) entry of the conflict + * has min(U) assured: some same-state min(U) configuration + * whose derivation is tail-independent ({@link #runtimeFaithful} - no + * widening joint in its context - and no boundary pop or foreign + * consumption, so it is realizable on every stack matching its + * context) and whose context covers the entry's, either exactly + * (common-min) or as a wildcard-tailed prefix (a shadow: on any stack + * where the entry is live the shadow is live too, so min(U) can never + * be absent from the runtime's live set). Entries matched by no real + * stack and inputs with an empty live set are error paths, where + * static/adaptive divergence is accepted. Returns the resolvable + * alternative, or 0 when some entry lacks assurance. + * + *

Boundary usage must be uniform for the same reason the + * exact-ambiguity trust requires it: a wildcard-tailed entry stands + * for a FAMILY of real stacks, and only when every configuration + * popped through the decision boundary (or none did) does the real + * outer context substitute into all alternatives identically. Mixed + * usage is the dangling-else shape: the iterate lineage dies in the + * outer frames on some inputs ({@code a,c>>x} in + * LeftRecursion/ReturnValueAndActionsList1_2, where alt 1 is + * boundary-free and alt 2 boundary-tainted), so closure-liveness is + * not input-viability and min-alt is not behavior-preserving.

+ */ + protected int utrustMinAlt(ATNConfigSet cs, BitSet conflicting, + boolean anyBoundary, boolean allBoundary) { + if (anyBoundary && !allBoundary) return 0; + int m = conflicting.nextSetBit(0); + // clean min(U) attestations by state, computed once per conflict: + // runtime-faithful, boundary- and foreign-free min(U) configs + Map> cleanMByState = new HashMap>(); + for (ATNConfig c : cs) { + if (c.alt == m + && (c.reachesIntoOuterContext & (BOUNDARY_TAINT|FOREIGN_CONSUME_TAINT)) == 0 + && runtimeFaithful(c)) { + cleanMByState.computeIfAbsent(c.state.stateNumber, k -> new ArrayList()).add(c); + } + } + if (cleanMByState.isEmpty()) return 0; + for (Map.Entry> e1 : groupByStateCtx(cs).entrySet()) { + List attestations = cleanMByState.get(e1.getKey()); + if (attestations == null) return 0; + for (PredictionContext entryCtx : e1.getValue().keySet()) { + boolean assured = false; + for (ATNConfig c : attestations) { + if (topPrefixWildcardMatch(c.context, entryCtx)) { + assured = true; + break; + } + } + if (!assured) return 0; + } + } + return m; + } + + /** + * Is {@code shadow}'s frame chain a top-frames prefix of + * {@code exact}'s, ending in the wildcard context - i.e. is + * {@code shadow}'s set of real stacks a superset of {@code exact}'s? + * Merged contexts are set unions, so the superset relation must hold + * branch by branch: EVERY branch of {@code exact} must be covered + * (a stack arriving through an uncovered branch is matched by the + * entry but not by the shadow - min(U) is not assured live on it; + * covering only the {@code 16 29 $} branch of {@code [16 29 $, 40 $]} + * is what misparsed {@code x BETWEEN y -> a AND b AND c}), while ANY + * branch of {@code shadow} may establish the coverage of one. + */ + protected static boolean topPrefixWildcardMatch(PredictionContext shadow, PredictionContext exact) { + if (exact != null && exact.size() > 1) { + for (int j = 0; j < exact.size(); j++) { + if (!topPrefixWildcardMatch(shadow, ctxBranch(exact, j))) return false; + } + return true; + } + if (shadow == null || shadow.isEmpty()) return true; + if (shadow.size() > 1) { + for (int i = 0; i < shadow.size(); i++) { + if (topPrefixWildcardMatch(ctxBranch(shadow, i), exact)) return true; + } + return false; + } + if (exact == null || exact.isEmpty()) return false; + int rs = shadow.getReturnState(0); + if (rs == PredictionContext.EMPTY_RETURN_STATE) return true; + if (exact.getReturnState(0) == PredictionContext.EMPTY_RETURN_STATE) return false; + return rs == exact.getReturnState(0) + && topPrefixWildcardMatch(shadow.getParent(0), exact.getParent(0)); + } + + private static PredictionContext ctxBranch(PredictionContext ctx, int i) { + PredictionContext p = ctx.getParent(i); + if (p == null) p = EmptyPredictionContext.Instance; + return SingletonPredictionContext.create(p, ctx.getReturnState(i)); + } + + /** + * Is this configuration's context free of widening joints - i.e. is + * its derivation one the runtime's own (widening-free) SLL closure + * also produces? See {@link #widenedJoints}. + */ + protected boolean runtimeFaithful(ATNConfig c) { + if (widenedJoints.isEmpty() || c.context == null) return true; + Boolean cached = faithCache.get(c.context); + if (cached != null) return cached; + Set visited = + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()); + Deque work = new ArrayDeque(); + work.add(c.context); + boolean faithful = true; + while (!work.isEmpty()) { + PredictionContext ctx = work.poll(); + if (ctx == null || !visited.add(ctx)) continue; + if (widenedJoints.contains(ctx)) { faithful = false; break; } + for (int i = 0; i < ctx.size(); i++) { + PredictionContext p = ctx.getParent(i); + if (p != null) work.add(p); + } + } + // cache the queried root only: a visited node's own subdag may be + // clean even when a sibling branch carries the joint + faithCache.put(c.context, faithful); + return faithful; + } + + /** Per-attempt memo for {@link #runtimeFaithful} (contexts share structure). */ + protected Map faithCache; + protected static boolean hasReturnState(PredictionContext ctx, int returnStateNumber) { return hasReturnState(ctx, returnStateNumber, java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); @@ -2378,6 +2602,11 @@ else if (r.dfa == null) { buf.append(String.format("take-rule: %d optional-postfix decisions; fires at %d conflict states%n", postfixDecisions, takeFires)); } + int utrust = 0; + for (Result r : results) utrust += r.utrustResolutions; + if (utrust > 0) { + buf.append(String.format("utrust: %d conflict states resolved to min-alt%n", utrust)); + } int maxKAnyAcyclic = 0; int maxKLLK = 0; From 117638ca519a5be49f7ae87e4f3357b5557421f9 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Tue, 21 Jul 2026 01:46:15 -0400 Subject: [PATCH 23/48] Shared-descent group analysis: rule-level factoring masks for budget escapes Generalizes the prefix-factor mask from token-prefix groups to semantic shared-descent groups: a set of a decision's alternatives whose derivations all transit a common rule R with zero token consumption (epsilon descent from the decision). At an escape state (cap or conflict) whose live alternatives are covered by such a group and whose live configurations are all inside an R invocation (R is their rule or a frame's return-state rule), the walker accepts with the group's alternative mask instead of escaping. Per-state prefix consistency is what makes the inside-R proof sufficient: a state is reached by a single consumed prefix, so configurations that entered R through a token-consuming call site land in different states than configurations that entered R through the decision's epsilon descent. The masks defer to adaptivePredict at runtime for now (the factored codegen is the follow-up), so this changes only table markers and sizes: 935 escape states across the eight grammars become mask accepts (ExprLoops 69->42... escapes 69->27, Trino -157, Duckdb -244, Redshift -178, Snowflake -99, Databricks -151, Bigquery -64). Three wiring fixes fell out of the battery: staticDFACanDefer must also treat mask-accept tables as defer-capable (an EXACT_AMBIG table with only masks previously got no adaptive fallback and silently fell through its match arms - the FuzzExpr degenerate-parse failure); mask-resolved conflicts are removed from approxConflicts/ contextSensitiveConflicts so an all-masked decision emits its table instead of collapsing to CONTEXT_SENSITIVE (same bookkeeping class as the utrust fix); and the stale-plan field is nulled per decision (classifyPrecedence runs before the plans are built). The FuzzExpr shape test now pins mask accepts + precedence dispatch. Battery: cargo 11 suites, tool-testsuite 694, runtime-testsuite rust.** 707, 3202-query differential corpus (2 known '::' error-path divergences), 7/7 pinned witnesses, perf unchanged. Signed-off-by: Bo Lin --- runtime/Rust/tests/fuzz_differential_tests.rs | 7 +- runtime/Rust/tests/gen/fuzzexprparser.rs | 11 +- .../antlr/v4/analysis/DecisionClassifier.java | 81 +++++++- .../v4/analysis/SharedDescentAnalyzer.java | 196 ++++++++++++++++++ tool/src/org/antlr/v4/analysis/StaticDFA.java | 10 + .../org/antlr/v4/codegen/ParserFactory.java | 2 +- 6 files changed, 289 insertions(+), 18 deletions(-) create mode 100644 tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java diff --git a/runtime/Rust/tests/fuzz_differential_tests.rs b/runtime/Rust/tests/fuzz_differential_tests.rs index 88eb868866..dcbc185541 100644 --- a/runtime/Rust/tests/fuzz_differential_tests.rs +++ b/runtime/Rust/tests/fuzz_differential_tests.rs @@ -199,12 +199,13 @@ fn test_escape_corners() { } } -/// The static parser must contain a hybrid table (adaptive escapes) and a -/// precedence dispatch; the adaptive twin must contain neither. +/// The static parser must contain a static table with mask accepts (the +/// shared-descent machinery engages on this grammar) and a precedence +/// dispatch; the adaptive twin must contain neither. #[test] fn test_generated_shape() { let stat = include_str!("gen/fuzzexprparser.rs"); - assert!(stat.contains("adaptive escapes"), "expected a hybrid table"); + assert!(stat.contains("mask accepts"), "expected mask-accept states"); assert!( stat.contains("precedence-dispatched"), "expected a dispatch" diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index e0513cf863..dbc57395f7 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -1188,7 +1188,7 @@ where // the serialized ATN is followed by 9 static SLL prediction tables (-Xstatic-dfa): // decision 6: precedence-dispatched over cutoffs [2, 3, 4, 6], tables [4 5 6 7 8] -// decision 2: LL(*) cyclic, 32 states, 15 adaptive escapes +// decision 2: LL(*) cyclic, 32 states, 15 mask accepts // decision 3: LL(k), k=1, 10 states // decision 5: LL(k), k=1, 5 states // decision 9: LL(k), k=2, 15 states @@ -1200,7 +1200,7 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); -static _serializedATN: [&'static str; 29] = [ +static _serializedATN: [&'static str; 30] = [ "CAIgsgEEAA4ABAIOAgQEDgQEBg4GBAgOCAQKDgoCAAIAAgAKACAQABQAGAAmEgACAAYALBAAAgACAAIC", "AgICAgICAgIGAj4QAgIEAgQCBgIGAgYKBkwQBhQGGAZSEgYCCAIIAggCCAYIXhAIAggCCAIIAggCCAII", "AggCCAIIAggCCAIIAggCCAoIfhAIFAgYCIQBEggCCgIKAgoCCgIKAgoCCgIKAgoCCgIKCgqeARAKFAoY", @@ -1215,13 +1215,14 @@ static _serializedATN: [&'static str; 29] = [ "hgGuAQYMBgCIAa4BCh4AAIoBjAEKGAAAjAGOAQYQCACOAZABChoAAJABrgECAAAAkgGUAQocAACUAaYB", "ChgAAJYBoAEGEAgAmAGaAQoCAACaAZ4BBhAIAJwBmAECAAAAngGkAQIAAACgAZwBAgAAAKABogECAAAA", "ogGoAQIAAACkAaABAgAAAKYBlgECAAAApgGoAQIAAACoAaoBAgAAAKoBrgEKGgAArAGGAQIAAACsAYgB", - "AgAAAKwBigECAAAArAGSAQIAAACuARYCAAAAFCIqPE5cfIABoAGmAawBDBIUBEDOAwAAAQEAAAQEBAIA", - "AAABAAEBAAAAAQEAAAEBAQEBAQEBAAQAAAQEAAAAAAAAAAAAAAAAAAQAAAQEAAAAAAAAAAAAHkhISHic", + "AgAAAKwBigECAAAArAGSAQIAAACuARYCAAAAFCIqPE5cfIABoAGmAawBDBIUBEDOAwAAAAAAAAQEBAIA", + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQEAAAAAAAAAAAAAAAAAAQAAAQEAAAAAAAAAAAAHkhISHic", "AZwBnAGcAZwBqAHGAeQB5AH8AfwB/AGaAqwC4gLiAuICngPOA84DzgPOA84DzgPOA84DzgMGBgIODgQY", "GAYcHAgeHgoBAQwCAg4EBBAGBhIICBQKChYOFhgBAQwCAg4EBBAGBhIICBQKChYOFhgYGBoBAQwCAg4E", "BBAGBhIKChYOFhgGBgIcHAIGBhwODh4YGCAcHCIeHiQGBiYODigYGCocHCweHi4ICDAKCjIMDAoOFjQI", "CDAKCjIMDAoOFjQYGDYKCjIMDAoOFjQBAQwCAg4EBBAGBhIICDgKCjoODhgQFDwWFhgBAQwCAg4EBBAG", - "BhIICDgKCjoODhgQFDwWFhgYGD4BAQwCAg4EBBAGBhIKCjoODhgQFDwWFhgABhQ2AAQEBAQCBAQEBAQA", + "BhIICDgKCjoODhgQFDwWFhgYGD4BAQwCAg4EBBAGBhIKCjoODhgQFDwWFhgeBAQCBAYEAgQaBAIEHgQC", + "BCAEAgQoBAIEKgQCBDAEAgQyBAIENAQCBDYEAgQ4BAIEOgQCBDwEAgQ+BAIEBhQ2AAQEBAQCBAQEBAQA", "AAAAAAAAAAAANjY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoKDAwMDg4WEBoaEgAKCh4ACAYCBAAAAAAA", "AB4eHh4eCgoCDg4EEBAGEhQIFhYEABIeVAACBgAEAgICAgICAgIIAgAAAAIAAAAAAAAAAAAAAAAYGBhU", "VFRUVFRUVFRUVFQGBgIYGAQcHAYeHggBAQoCAgwEBA4GBhAICBIKChQMDBYOFhgYGBoaGhwAARIwAAQE", diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 9fef0d3f48..c3b225f25e 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -195,6 +195,9 @@ public static class Result { /** Conflict states resolved to min(U) by the uniform-widening * trust (every context entry has an assured min attestation). */ public int utrustResolutions; + /** Escape states accepting a shared-descent group's alternative + * mask (every live configuration starts via the group's rule). */ + public int descentMaskStates; /** Dry-run: the decision is an optional-postfix (X Y?) shape. */ public boolean hasPostfixShape; @@ -491,6 +494,25 @@ public Result(DecisionState decisionState) { /** ...of which the widened call is guard-reachable (debug counter). */ protected int widenGuarded; + /** Lazily built shared-descent dry-run analyzer. */ + protected SharedDescentAnalyzer descentAnalyzer; + /** The shared-descent plan of the decision being classified. */ + protected SharedDescentAnalyzer.Plan currentDescentPlan; + + /** Do all live configurations of this state genuinely start via R? */ + protected boolean allStartViaR(Set configs, DecisionState s, int ruleR) { + for (ATNConfig c : configs) { + if (!descentAnalyzer().startsViaR(c, s, ruleR)) return false; + } + return true; + } + protected SharedDescentAnalyzer descentAnalyzer() { + if (descentAnalyzer == null) { + descentAnalyzer = new SharedDescentAnalyzer(g, atn, callByFollowState()); + } + return descentAnalyzer; + } + /** Analyzer for prefix-factorable decisions (alt-mask dry run). */ protected final PrefixFactorAnalyzer factorAnalyzer; /** Analyzer for optional-postfix (X Y?) decisions (take-rule dry run). */ @@ -523,6 +545,7 @@ public Result classify(DecisionState s) { Result res = new Result(s); this.currentFactorPlan = null; this.currentPostfixShape = null; + this.currentDescentPlan = null; if (s.nonGreedy) { res.category = Category.NON_GREEDY; return res; @@ -540,6 +563,8 @@ public Result classify(DecisionState s) { // alt-mask dry run: compute the prefix-factor plan up front; the // construction attempts count the states it would resolve. this.currentFactorPlan = factorAnalyzer.analyze(s); + // semantic shared-descent plan (rule-level factoring) + this.currentDescentPlan = descentAnalyzer().buildPlan(s); // optional-postfix take-rule dry run this.currentPostfixShape = postfixAnalyzer.analyze(s); if (currentFactorPlan.hasGroups() @@ -1389,7 +1414,23 @@ else if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { acceptMasks.set(d, altBits(factorGroup.alts)); } else { - acceptAlts.set(d, StaticDFA.ESCAPE); + SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null + && !currentFactorPlan.hasGroups() + ? currentDescentPlan.groupCovering(alts) : null; + if (descentGroup != null && allStartViaR(configs, s, descentGroup.rule)) { + res.descentMaskStates++; + res.approxConflicts.remove(conflicting); + res.contextSensitiveConflicts.remove(conflicting); + res.exactAmbigConflicts.add(conflicting); + acceptMasks.set(d, altBits(descentGroup.alts)); + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("DESCENT-MASK d=%d state=%d rule=%s alts=%s%n", + s.decision, d, g.getRule(descentGroup.rule).name, descentGroup.alts); + } + } + else { + acceptAlts.set(d, StaticDFA.ESCAPE); + } } if ("utrust".equals(System.getProperty("antlr.dfa.debug"))) { utrustProbe(s, d, cs, conflicting, exact, factorGroup != null, anyBoundary, allBoundary); @@ -1398,15 +1439,15 @@ else if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { System.err.printf("ESCAPE-CONFLICT d=%d state=%d depth=%d exact=%s hard=%s anyB=%s allB=%s trustEA=%s alts=%s%n", s.decision, d, stateDepth.get(d), exact, widenedTainted, anyBoundary, allBoundary, trustExactAmbig, conflicting); - if ("full".equals(System.getProperty("antlr.dfa.debug"))) { - for (ATNConfig c : cs) { - System.err.printf(" alt=%d rule=%s state=%d taint=%d ctx=%s%n", - c.alt, g.getRule(c.state.ruleIndex).name, - c.state.stateNumber, c.reachesIntoOuterContext, - c.context); + if ("full".equals(System.getProperty("antlr.dfa.debug"))) { + for (ATNConfig c : cs) { + System.err.printf(" alt=%d rule=%s state=%d taint=%d ctx=%s%n", + c.alt, g.getRule(c.state.ruleIndex).name, + c.state.stateNumber, c.reachesIntoOuterContext, + c.context); + } } } - } } else if (abortOnUntrustedConflict) { // not a trusted exact ambiguity: no widening level @@ -1434,7 +1475,20 @@ else if (abortOnUntrustedConflict) { acceptMasks.set(d, altBits(factorGroup.alts)); } else { - acceptAlts.set(d, StaticDFA.ESCAPE); + SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null + && !currentFactorPlan.hasGroups() + ? currentDescentPlan.groupCovering(alts) : null; + if (descentGroup != null && allStartViaR(configs, s, descentGroup.rule)) { + res.descentMaskStates++; + acceptMasks.set(d, altBits(descentGroup.alts)); + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("DESCENT-MASK d=%d state=%d rule=%s alts=%s%n", + s.decision, d, g.getRule(descentGroup.rule).name, descentGroup.alts); + } + } + else { + acceptAlts.set(d, StaticDFA.ESCAPE); + } } continue; } @@ -2607,6 +2661,15 @@ else if (r.dfa == null) { if (utrust > 0) { buf.append(String.format("utrust: %d conflict states resolved to min-alt%n", utrust)); } + int descentPlans = 0, descentMasks = 0; + for (Result r : results) { + if (r.descentMaskStates > 0) descentPlans++; + descentMasks += r.descentMaskStates; + } + if (descentMasks > 0) { + buf.append(String.format("descent: %d decisions with shared-descent groups; %d mask-accept states%n", + descentPlans, descentMasks)); + } int maxKAnyAcyclic = 0; int maxKLLK = 0; diff --git a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java new file mode 100644 index 0000000000..c5ce7630eb --- /dev/null +++ b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this source code is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.analysis; + +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNConfig; +import org.antlr.v4.runtime.atn.ATNState; +import org.antlr.v4.runtime.atn.DecisionState; +import org.antlr.v4.runtime.atn.PredictionContext; +import org.antlr.v4.runtime.atn.RuleStopState; +import org.antlr.v4.runtime.atn.RuleTransition; +import org.antlr.v4.runtime.atn.Transition; +import org.antlr.v4.tool.Grammar; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Semantic shared-descent group analysis (the generalization of the + * prefix-factor mask to rule-level shared descents). A group of + * alternatives of a decision starts via a common rule R when + * each member alternative descends to an R invocation with zero token + * consumption (epsilon-only descent from the decision). At an escape + * state whose live alternatives are covered by such a group and whose + * live configurations all genuinely transited R at the decision's first + * consuming invocation, the static walker may accept with the group's + * alternative mask: the parser calls {@code R()} once and resolves the + * choice at the post-R tail - the table never enumerates the descent + * parse that exhausts its construction budget. + * + *

The per-configuration proof ({@link #startsViaR}) is the rigorous + * core: a configuration starts via R iff its call chain contains an R + * invocation frame (the callee of some context frame is R) whose call + * site lies on an epsilon-only path from the decision entry, with only + * epsilon-descent frames below it. Configurations whose chain is + * truncated by a widening joint before reaching an R frame, or that + * reach R through a token-consuming call site (e.g. inside a TRIM + * argument), fail the proof - so the mask is only accepted where the + * shared descent is genuine.

+ */ +public class SharedDescentAnalyzer { + + /** One shared-descent group: member alternatives starting via {@link #rule}. */ + public static class Group { + public final int rule; + public final BitSet alts; + + public Group(int rule, BitSet alts) { + this.rule = rule; + this.alts = alts; + } + } + + /** Per-decision plan: the shared-descent groups of the decision. */ + public static class Plan { + public final List groups = new ArrayList(); + + public boolean hasGroups() { return !groups.isEmpty(); } + + /** The group whose member alternatives cover {@code live}, or null. */ + public Group groupCovering(BitSet live) { + for (Group grp : groups) { + BitSet covered = (BitSet)grp.alts.clone(); + covered.and(live); + if (covered.equals(live)) return grp; + } + return null; + } + } + + private final Grammar g; + private final ATN atn; + private final Map callByFollowState; + private final Map> candidateCache = new HashMap>(); + + public SharedDescentAnalyzer(Grammar g, ATN atn, Map callByFollowState) { + this.g = g; + this.atn = atn; + this.callByFollowState = callByFollowState; + } + + /** Build the decision's shared-descent plan. */ + public Plan buildPlan(DecisionState s) { + Plan plan = new Plan(); + for (int r : candidates(s)) { + BitSet members = new BitSet(); + for (int a = 1; a <= s.getNumberOfTransitions(); a++) { + if (altStartsViaR(s, a, r)) members.set(a); + } + if (members.cardinality() >= 2) plan.groups.add(new Group(r, members)); + } + return plan; + } + + /** + * Is this configuration inside an R invocation - R is its own rule, + * or the rule of some frame's return state? Widening joints hide the + * R-entry call itself, but the joint's frame still carries R's rule, + * and per-state prefix consistency supplies the rest: the static + * state is reached by a single consumed prefix, so configurations + * that entered R through a token-consuming call site (a TRIM + * argument, a subscript bracket) land in different states than + * configurations that entered R through the decision's epsilon + * descent. Merged contexts: any branch may establish the derivation. + */ + public boolean startsViaR(ATNConfig c, DecisionState s, int ruleR) { + if (c.state.ruleIndex == ruleR) return true; + if (c.context == null) return false; + Set seen = + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()); + Deque work = new ArrayDeque(); + work.add(c.context); + while (!work.isEmpty()) { + PredictionContext ctx = work.poll(); + if (ctx == null || !seen.add(ctx)) continue; + for (int i = 0; i < ctx.size(); i++) { + int rs = ctx.getReturnState(i); + if (rs != PredictionContext.EMPTY_RETURN_STATE + && atn.states.get(rs).ruleIndex == ruleR) { + return true; + } + PredictionContext p = ctx.getParent(i); + if (p != null) work.add(p); + } + } + return false; + } + + /** + * Rules invocable from the decision via epsilon-only descents, in + * BFS order (shallowest shared rules first). + */ + private List candidates(DecisionState s) { + List rules = candidateCache.get(s.decision); + if (rules == null) { + Set seen = new java.util.LinkedHashSet(); + Set seenStates = new HashSet(); + Deque work = new ArrayDeque(); + for (int i = 0; i < s.getNumberOfTransitions(); i++) work.add(s.transition(i).target); + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seenStates.add(st) || st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + seen.add(((RuleTransition)t).target.ruleIndex); + work.add(t.target); + } + else if (t.isEpsilon()) { + work.add(t.target); + } + } + } + rules = new ArrayList(seen); + candidateCache.put(s.decision, rules); + } + return rules; + } + + /** + * Does alternative {@code alt} descend to an R invocation with zero + * token consumption (on some path)? + */ + private boolean altStartsViaR(DecisionState s, int alt, int ruleR) { + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + work.add(s.transition(alt-1).target); + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st) || st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + if (((RuleTransition)t).target.ruleIndex == ruleR) return true; + work.add(t.target); + } + else if (t.isEpsilon()) { + work.add(t.target); + } + } + } + return false; + } + +} diff --git a/tool/src/org/antlr/v4/analysis/StaticDFA.java b/tool/src/org/antlr/v4/analysis/StaticDFA.java index a00dbd90ed..ed0c17507d 100644 --- a/tool/src/org/antlr/v4/analysis/StaticDFA.java +++ b/tool/src/org/antlr/v4/analysis/StaticDFA.java @@ -44,6 +44,16 @@ public boolean hasEscapes() { return false; } + /** True if any state of this table is a mask-accept state: a runtime + * prediction driven by it can receive an alternative mask it cannot + * execute (no factored arm), and must defer to {@code adaptivePredict}. */ + public boolean hasMasks() { + for (long m : acceptMasks) { + if (m != 0) return true; + } + return false; + } + public final int decision; public final int numStates; /** Predicted alternative per state; 0 = not an accept state; {@link #ESCAPE} = escape. */ diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index ff7da3058b..8d83a03855 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -279,7 +279,7 @@ protected boolean staticDFACanDefer(int decision) { } org.antlr.v4.analysis.StaticDFA dfa = g.staticDecisionDFAs != null ? g.staticDecisionDFAs.get(decision) : null; - return dfa != null && dfa.hasEscapes(); + return dfa != null && (dfa.hasEscapes() || dfa.hasMasks()); } /** Like getComplexEBNFBlock but driving the decision from a static DFA table. */ From 831b8c8f3445d2ea22830668f1ba2d2dcdd0dfb0 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Wed, 22 Jul 2026 01:34:08 -0400 Subject: [PATCH 24/48] Shared-descent factoring via resume mode: execute the common rule once, re-descend top-down The shared-descent group's factored block parses the common rule R once (neutral, muted error listeners, invoking state set to a valid call site), then start_resume un-grafts the parsed node and rewinds the token stream to the prefix start. The ordinary alternatives then re-descend with their natural prediction machinery on the prefix tokens - consuming nothing, since the group's first-consumer proof requires an epsilon descent - until the stored rule short-circuits via resume_take, which grafts the node under the caller's context and restores the stream to the tail position. This replaces the rejected alternatives: probe+reparse (provably exponential on nested prefixes) and bottom-up resume functions (heavy code duplication against ANTLR's top-down flow). No forcing is needed anywhere: the rewound stream positions each prediction on the right tokens, the descent is consumption-free, and every alt body is the ordinary one, verbatim. Soundness rests on the rigorous first-consumer proof: every live configuration of a mask-accept state must contain an R invocation as the decision's first consuming invocation (a deepest R segment on its call chain whose below-segments all lie on the epsilon descent from the decision), so the neutral R call can never fail on a valid mask-covered input. On invalid inputs the neutral parse is muted and its result discarded before deferring to adaptivePredict, so error reporting matches the adaptive engine; nested descent blocks defer when resume is already active. Machine: ParserBase resume state + start_resume/resume_take/ resume_active/abort_resume/begin_mute/end_mute/discard_graft/ syntax_error_count; resume_take hooks at the top of resume-target rule functions (public entries and _rec alike, since left-recursive alt bodies and operands call _rec); DescentAltBlock/DescentGroup codegen emitted only when the table actually carries a group's mask (dead plans add no adaptive widen paths); dispatch plan (explicit tail arms + nullable default) with empty-mandatory tails treated as nullable. The walker itself is unchanged (Stage 1 masks). Fixes caught by the battery: resume_take must match the stored rule (any-rule take livelocked the recursion-context machinery); the tail token must be read before start_resume rewinds the stream; mark() is a stubbed bookmark API - positions use index()/seek(); the neutral node needs a real call-site invoking state (error recovery re-reads it); DeadPlan blocks must not be emitted. Battery: cargo 11 suites, tool-testsuite 694, runtime-testsuite rust.** 707, 3202-query differential corpus (only the 2 known '::' error-path divergences), 7/7 pinned witnesses, perf: Q1 2.28us vs 5.20us adaptive (2.3x), user query 2.5x, star/alias family 3.3x (6.6us vs 21.9us). Signed-off-by: Bo Lin --- runtime/Rust/src/parser.rs | 117 +++++++ runtime/Rust/tests/gen/fuzzexprparser.rs | 95 ++++-- runtime/Rust/tests/gen/staticdfaparser.rs | 3 + .../v4/tool/templates/codegen/Rust/Rust.stg | 83 +++++ .../antlr/v4/analysis/DecisionClassifier.java | 14 + .../v4/analysis/SharedDescentAnalyzer.java | 287 ++++++++++++++++-- .../org/antlr/v4/codegen/ParserFactory.java | 86 +++++- .../v4/codegen/model/DescentAltBlock.java | 41 +++ .../antlr/v4/codegen/model/DescentGroup.java | 58 ++++ .../antlr/v4/codegen/model/RuleFunction.java | 2 + tool/src/org/antlr/v4/tool/Grammar.java | 6 + tool/src/org/antlr/v4/tool/Rule.java | 5 + 12 files changed, 748 insertions(+), 49 deletions(-) create mode 100644 tool/src/org/antlr/v4/codegen/model/DescentAltBlock.java create mode 100644 tool/src/org/antlr/v4/codegen/model/DescentGroup.java diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index c6e35a6ece..61d69c5c27 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -147,6 +147,13 @@ where parse_listeners: Vec>, _syntax_errors: Cell, error_listeners: Vec>, + /// Resume-mode state of a shared-descent factoring: the parsed + /// prefix context, its rule, and the stream position just past it + /// (the tail); see `start_resume`. + resume_node: Option<(&'arena TreeNode<'input, 'arena, Node, TF::Tok>, usize, isize)>, + /// Error listeners muted during neutral prefix parses (stacked for + /// nesting); see `begin_mute`. + muted_error_listeners: Vec>>, pub arena: &'arena Arena, ext: Ext, @@ -443,6 +450,8 @@ where interp: Some(interp), global_cache_threshold: 0, ctx: std::ptr::null_mut(), + resume_node: None, + muted_error_listeners: Vec::new(), build_parse_trees: true, matched_eof: false, state: -1, @@ -519,6 +528,114 @@ where self.dfa_walk(decision) } + /// Mute error listeners (the neutral prefix parse of a descent + /// block must not fire spurious reports on inputs it cannot + /// complete). Pair with [`Self::end_mute`]. + #[doc(hidden)] + pub fn begin_mute(&mut self) { + let el = std::mem::take(&mut self.error_listeners); + self.muted_error_listeners.push(el); + } + + /// Restore listeners muted by [`Self::begin_mute`]. + #[doc(hidden)] + pub fn end_mute(&mut self) { + if let Some(el) = self.muted_error_listeners.pop() { + self.error_listeners = el; + } + } + + /// Remove a grafted context from its parent's children (an errorful + /// neutral parse's result is thrown away before deferring to the + /// adaptive engine). + #[doc(hidden)] + #[allow(invalid_reference_casting)] + pub fn discard_graft(&mut self, node: &'arena TreeNode<'input, 'arena, Node, TF::Tok>) { + if self.build_parse_trees { + if let Some(parent) = node.get_parent() { + unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); + } + } + } + + /// The number of syntax errors reported so far; a neutral prefix + /// parse that moves this count was errorful. + #[doc(hidden)] + pub fn syntax_error_count(&self) -> i32 { + self._syntax_errors.get() + } + + /// Begin resume mode after a shared-descent group's common rule was + /// parsed once: un-graft the parsed node from the current context, + /// remember it with its rule and the tail stream position, and + /// rewind the stream to `prefix_pos` (the position saved before the + /// common rule was called). The re-descent through the ordinary + /// alternatives then predicts on the prefix tokens (consuming + /// nothing, the descent being epsilon by construction) until + /// [`Self::resume_take`] short-circuits the stored rule. + #[doc(hidden)] + #[allow(invalid_reference_casting)] + pub fn start_resume( + &mut self, + node: &'arena TreeNode<'input, 'arena, Node, TF::Tok>, + rule: usize, + prefix_pos: isize, + ) { + let tail_pos = self.input.index(); + if self.build_parse_trees { + if let Some(parent) = node.get_parent() { + self.set_current_ctx(Some(parent)); + unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); + } + } + self.resume_node = Some((node, rule, tail_pos)); + self.input.seek(prefix_pos); + } + + /// Is resume mode active (a nested descent block must defer to the + /// adaptive engine rather than start another resume)? + #[doc(hidden)] + pub fn resume_active(&self) -> bool { + self.resume_node.is_some() + } + + /// Take the stored prefix context when `rule` is called in resume + /// mode: graft it under the current context, restore the stream to + /// the tail position, and end resume mode. Returns None when + /// inactive or the rule does not match. + #[doc(hidden)] + #[allow(invalid_reference_casting)] + pub fn resume_take( + &mut self, + rule: usize, + ) -> Option<&'arena TreeNode<'input, 'arena, Node, TF::Tok>> { + if self.resume_node.map(|(_, r, _)| r) != Some(rule) { + return None; + } + let (node, _, tail_pos) = self.resume_node.take()?; + if self.build_parse_trees { + // re-stamp the invoking state to the resuming call site (the + // neutral parse created the node with a generic one) + unsafe { &mut *(node as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.set_invoking_state(self.get_state()); + let parent = self.ctx(); + unsafe { &mut *(node as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.set_parent(parent); + if let Some(parent) = parent { + unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.add_child(node); + } + } + self.input.seek(tail_pos); + Some(node) + } + + /// Abort resume mode on error unwind: restore the stream to the + /// tail position and clear the state. + #[doc(hidden)] + pub fn abort_resume(&mut self) { + if let Some((_, _, tail_pos)) = self.resume_node.take() { + self.input.seek(tail_pos); + } + } + /// The shared static-table walk: the prediction of `decision` as an /// alternative mask, or `0` when the table defers to the adaptive /// engine. diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index dbc57395f7..3332b0301e 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -460,32 +460,69 @@ where let result: Result<(), ANTLRError> = (|| { recog.base.set_state(30); recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } } { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule e*/ - recog.base.set_state(25); - recog.e_rec(0)?; - recog.base.set_state(26); - recog.base.match_token(FuzzExpr_T__2,&mut recog.err_handler)?; - /*InvokeRule name*/ - recog.base.set_state(27); - recog.name()?; - } + match { let _m = recog.base.dfa_predict_mask(2)?; + match _m { + 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x == 0x3 && !recog.base.resume_active() => { + let _pos0 = recog.input.index(); + recog.base.set_state(25); + recog.base.begin_mute(); + let _errs = recog.base.syntax_error_count(); + match recog.e() { + Err(e) if !e.is_recoverable() => return Err(e), + Err(_) => { + recog.base.end_mute(); + recog.input.seek(_pos0); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + recog.base.end_mute(); + if recog.base.syntax_error_count() != _errs { + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + recog.base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node)); + recog.input.seek(_pos0); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream; + // only then rewind into resume mode + let _tailbit = match recog.input.la(1) { + FuzzExpr_T__2 => 0x1, + _ => 0x2 + }; + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e, _pos0); + _tailbit + } + }, + } + }, + 0x3 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + m => m, + } } { + x if x == 0x1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(25); + recog.e_rec(0)?; + recog.base.set_state(26); + recog.base.match_token(FuzzExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(27); + recog.name()?; } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - /*InvokeRule e*/ - recog.base.set_state(29); - recog.e_rec(0)?; - } + }, + x if x == 0x2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + /*InvokeRule e*/ + recog.base.set_state(29); + recog.e_rec(0)?; } - + } _ => {} } Ok(()) @@ -826,12 +863,20 @@ where { #[inline] pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - self.e_rec(0) + { + let recog = &mut *self; + if let Some(_node) = recog.base.resume_take(RULE_e) { + return Ok(_node.as_rule_context().unwrap()); + } + }self.e_rec(0) } fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { dbt_antlr4::maybe_grow_stack!({ let recog = self; + if let Some(_node) = recog.base.resume_take(RULE_e) { + return Ok(_node.as_rule_context().unwrap()); + } let _parentctx = recog.base.take_ctx(); let _parentState = recog.base.get_state(); recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_e, _p)?; diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index dbfe7adf7d..820d6a399a 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -1082,6 +1082,9 @@ where pub fn name(&mut self,) -> Result<&'arena NameContextAll<'input, 'arena, TF::Tok>, ANTLRError> { dbt_antlr4::maybe_grow_stack!({ let recog = self; + if let Some(_node) = recog.base.resume_take(RULE_name) { + return Ok(_node.as_rule_context().unwrap()); + } let _parentctx = recog.base.take_ctx(); recog.base.enter_rule(NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_name)?; let _local_ctx_fn = |recog: &Self| -> &'arena NameContext {recog.ctx().unwrap().as_rule_context().unwrap()}; diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index 59b565d343..12c3639d3c 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -540,6 +540,7 @@ where }>pub fn (&mut self,) -> Result\<&'arena All\<'input, 'arena, TF::Tok>, ANTLRError> { dbt_antlr4::maybe_grow_stack!({ let recog = self; + let _parentctx = .base.take_ctx(); .base.enter_rule(Ext::create(.get_arena(), _parentctx, .get_state()}>)?, , RULE_)?; let _local_ctx_fn = |recog: &Self| -> &'arena \ {recog.ctx().unwrap().as_rule_context().unwrap()}; @@ -582,12 +583,17 @@ where { #[inline] }>pub fn (&mut self,) -> Result\<&'arena All\<'input, 'arena, TF::Tok\>, ANTLRError> { + { + let recog = &mut *self; + + } self._rec(0}>) } fn _rec(&mut self, _p: i32}>) -> Result\<&'arena All\<'input, 'arena, TF::Tok\>, ANTLRError> { dbt_antlr4::maybe_grow_stack!({ let recog = self; + let _parentctx = .base.take_ctx(); let _parentState = .base.get_state(); .base.enter_recursion_rule(Ext::create(.get_arena(), _parentctx, .get_state()}>)?, , RULE_, _p)?; @@ -834,6 +840,83 @@ FactoredTailArm(t, body) ::= << \} >> +// Shared-descent group dispatch (rule-level factoring, "resume mode"): +// a walker mask covering a shared-descent group calls the group's +// common rule once, then start_resume rewinds the stream to the prefix +// start so the ordinary alternatives re-descend with natural +// prediction on the prefix tokens (consuming nothing - the descent is +// epsilon by construction) until the stored rule short-circuits via +// resume_take, which restores the stream to the tail. +descentMaskPredict(choice, groups) ::= << +{ let _m = .base.dfa_predict_mask()?; + match _m { + 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), + + m => m, + } } +>> + +DescentGroup(g, tails) ::= << + x if x == && !.base.resume_active() => { + let _pos0 = .input.index(); + .base.set_state(); + .base.begin_mute(); + let _errs = .base.syntax_error_count(); + match .() { + Err(e) if !e.is_recoverable() => return Err(e), + Err(_) => { + .base.end_mute(); + .input.seek(_pos0); + 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) + }, + Ok(_node) => { + .base.end_mute(); + if .base.syntax_error_count() != _errs { + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + .base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node)); + .input.seek(_pos0); + 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream; + // only then rewind into resume mode + let _tailbit = match .input.la(1) { + + _ => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) + }; + .base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_, _pos0); + _tailbit + } + }, + } + }, + => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), +>> + +Tail(t) ::= " => ," + +// Resume-mode short-circuit at the top of a resume-target rule: when a +// shared-descent re-descent reaches the common rule, return the stored +// prefix context (grafted under the caller, stream restored to the +// tail by resume_take) instead of parsing it again. +resumeTakeHook(currentRule) ::= << +if let Some(_node) = recog.base.resume_take(RULE_) { + return Ok(_node.as_rule_context().unwrap()); +} +>> + +DescentAltBlock(choice, preamble, singletons, groups, error) ::= << +.base.set_state(); +.err_handler.sync(&mut .base)?; +.base.input.lt(1).map(|t| t as _);})> + +match { + + _ => {} +} +>> + DFAOptionalBlock(choice, alts, error) ::= << .base.set_state(); .err_handler.sync(&mut .base)?; diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index c3b225f25e..245a98c7b6 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -200,6 +200,8 @@ public static class Result { public int descentMaskStates; /** Dry-run: the decision is an optional-postfix (X Y?) shape. */ public boolean hasPostfixShape; + /** The decision's shared-descent plan, when it has groups. */ + public SharedDescentAnalyzer.Plan descentPlan; public Result(DecisionState decisionState) { this.decisionState = decisionState; @@ -598,11 +600,13 @@ public Result classify(DecisionState s) { Result hybrid = classifyHybrid(s); if (hybrid != null && hybrid.dfa != null) { if (currentFactorPlan.hasGroups()) hybrid.factorPlan = currentFactorPlan; + if (currentDescentPlan.hasGroups()) hybrid.descentPlan = currentDescentPlan; hybrid.hasPostfixShape = currentPostfixShape != null; return hybrid; } } if (currentFactorPlan.hasGroups()) outcome.factorPlan = currentFactorPlan; + if (currentDescentPlan.hasGroups()) outcome.descentPlan = currentDescentPlan; outcome.hasPostfixShape = currentPostfixShape != null; return outcome; } @@ -2492,6 +2496,7 @@ public static void buildTables(Grammar g) { Map precTables = new LinkedHashMap(); Map factorPlans = new LinkedHashMap(); + Map descentPlans = new HashMap(); for (DecisionState s : g.atn.decisionToState) { // the LL(1) fast path already covers disjoint decisions if (g.decisionLOOK != null && s.decision < g.decisionLOOK.size() @@ -2508,10 +2513,19 @@ else if (r.precDfa != null) { if (r.factorPlan != null && r.factorPlan.hasGroups()) { factorPlans.put(s.decision, r.factorPlan); } + if (r.descentPlan != null && r.descentPlan.hasGroups()) { + descentPlans.put(s.decision, r.descentPlan); + } } g.staticDecisionDFAs = tables; g.staticPrecedenceDFAs = precTables; g.staticFactorPlans = factorPlans; + g.staticDescentPlans = descentPlans; + for (SharedDescentAnalyzer.Plan plan : descentPlans.values()) { + for (SharedDescentAnalyzer.Group grp : plan.groups) { + if (grp.codegenable) g.getRule(grp.rule).resumeTarget = true; + } + } addSyntheticContinuationStates(g, factorPlans); } diff --git a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java index c5ce7630eb..a8acaeaa40 100644 --- a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java +++ b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java @@ -13,7 +13,9 @@ import org.antlr.v4.runtime.atn.PredictionContext; import org.antlr.v4.runtime.atn.RuleStopState; import org.antlr.v4.runtime.atn.RuleTransition; +import org.antlr.v4.runtime.atn.LL1Analyzer; import org.antlr.v4.runtime.atn.Transition; +import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.tool.Grammar; import java.util.ArrayDeque; @@ -55,11 +57,29 @@ public class SharedDescentAnalyzer { public static class Group { public final int rule; public final BitSet alts; + /** Explicit tail arms (member alt -> tail token set); the default + * alt ({@link #defaultAlt}) catches everything else. */ + public final Map explicitArms = new HashMap(); + /** The member alt whose continuation after R is nullable (it may + * complete right after R); the tail dispatch's default arm. 0 + * when none (all-explicit dispatch, with an adaptive fallback). */ + public int defaultAlt; + /** The dispatch plan is sound: exactly one nullable default and + * pairwise-disjoint explicit arms (each disjoint from the + * default's viable set). */ + public boolean codegenable; public Group(int rule, BitSet alts) { this.rule = rule; this.alts = alts; } + + /** A state on the epsilon descent whose transition invokes + * {@link #rule}: a valid call-site for the neutral parse (the + * generated block sets the parser's invoking state to it before + * calling the common rule, so error recovery sees a proper + * call frame). */ + public int callSiteState; } /** Per-decision plan: the shared-descent groups of the decision. */ @@ -83,6 +103,7 @@ public Group groupCovering(BitSet live) { private final ATN atn; private final Map callByFollowState; private final Map> candidateCache = new HashMap>(); + private final Map> callSitesCache = new HashMap>(); public SharedDescentAnalyzer(Grammar g, ATN atn, Map callByFollowState) { this.g = g; @@ -98,45 +119,237 @@ public Plan buildPlan(DecisionState s) { for (int a = 1; a <= s.getNumberOfTransitions(); a++) { if (altStartsViaR(s, a, r)) members.set(a); } - if (members.cardinality() >= 2) plan.groups.add(new Group(r, members)); + if (members.cardinality() >= 2) { + Group grp = new Group(r, members); + grp.callSiteState = firstCallSite(s, r); + analyzeDispatch(s, grp); + plan.groups.add(grp); + if ("descent".equals(System.getProperty("antlr.dfa.debug")) && grp.codegenable) { + System.err.printf("DESCENT-PLAN d=%d rule=%s alts=%s default=%d arms=%s%n", + s.decision, g.getRule(r).name, members, grp.defaultAlt, grp.explicitArms); + } + } } return plan; } /** - * Is this configuration inside an R invocation - R is its own rule, - * or the rule of some frame's return state? Widening joints hide the - * R-entry call itself, but the joint's frame still carries R's rule, - * and per-state prefix consistency supplies the rest: the static - * state is reached by a single consumed prefix, so configurations - * that entered R through a token-consuming call site (a TRIM - * argument, a subscript bracket) land in different states than - * configurations that entered R through the decision's epsilon - * descent. Merged contexts: any branch may establish the derivation. + * The dispatch analysis of one group: every member alt's mandatory + * continuation after R (its FIRST tokens, FOLLOW tokens included iff + * the continuation is nullable). Explicit arms are the non-nullable + * continuations; the default is the single nullable one. Over- + * approximating (grammar-wide pops, full callee LOOK) can only + * reject sound groups, never accept unsound ones. */ - public boolean startsViaR(ATNConfig c, DecisionState s, int ruleR) { - if (c.state.ruleIndex == ruleR) return true; - if (c.context == null) return false; - Set seen = - java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()); - Deque work = new ArrayDeque(); - work.add(c.context); + private void analyzeDispatch(DecisionState s, Group grp) { + LL1Analyzer ll1 = new LL1Analyzer(atn); + Map mandatory = new HashMap(); + Set nullable = new HashSet(); + for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { + Set nul = new HashSet(); + IntervalSet t = mandatoryTail(s, a, grp.rule, ll1, nul); + mandatory.put(a, t); + // an empty mandatory tail is a degenerate continuation: the + // alternative completes with no discriminating token, so it + // belongs to the default arm, not an explicit one + if (!nul.isEmpty() || t.isNil()) nullable.add(a); + } + if (nullable.size() > 1) return; + IntervalSet defaultSet = nullable.isEmpty() + ? new IntervalSet() : mandatory.get(nullable.iterator().next()); + IntervalSet acc = new IntervalSet(); + for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { + if (nullable.contains(a)) continue; + IntervalSet t = mandatory.get(a); + for (int tok : t.toArray()) { + if (acc.contains(tok)) return; + acc.add(tok); + } + for (int tok : defaultSet.toArray()) { + if (t.contains(tok)) return; + } + } + if (!nullable.isEmpty()) grp.defaultAlt = nullable.iterator().next(); + boolean anyTokens = false; + for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { + if (!nullable.contains(a)) { + grp.explicitArms.put(a, mandatory.get(a)); + if (!mandatory.get(a).isNil()) anyTokens = true; + } + } + // a dispatch needs something to discriminate on: a default arm, + // or at least one non-empty explicit arm + grp.codegenable = grp.defaultAlt != 0 || anyTokens; + } + + /** + * FIRST tokens of alternative {@code alt}'s mandatory continuation + * after R (over-approximated); {@code nullable} is set when the + * continuation can complete the alternative with no post-R token, + * in which case the decision rule's FOLLOW is included. + */ + private IntervalSet mandatoryTail(DecisionState s, int alt, int ruleR, LL1Analyzer ll1, + Set nullable) { + IntervalSet tokens = new IntervalSet(); + Set calls = new HashSet(); + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + work.add(s.transition(alt-1).target); + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st) || st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + if (((RuleTransition)t).target.ruleIndex == ruleR) calls.add(((RuleTransition)t).followState); + else work.add(t.target); + } + else if (t.isEpsilon()) { + work.add(t.target); + } + } + } + for (ATNState follow : calls) { + tailFirst(follow, s.ruleIndex, tokens, nullable, ll1, new HashSet()); + } + return tokens; + } + + private void tailFirst(ATNState st, int decisionRule, IntervalSet tokens, + Set nullable, LL1Analyzer ll1, Set seen) { + Deque work = new ArrayDeque(); + work.add(st); while (!work.isEmpty()) { - PredictionContext ctx = work.poll(); - if (ctx == null || !seen.add(ctx)) continue; + ATNState p = work.poll(); + if (!seen.add(p)) continue; + for (int i = 0; i < p.getNumberOfTransitions(); i++) { + Transition t = p.transition(i); + if (t instanceof RuleTransition) { + tokens.addAll(ll1.LOOK(t.target, null)); + work.add(((RuleTransition)t).followState); + } + else if (t.isEpsilon()) { + if (p instanceof RuleStopState) { + if (p.ruleIndex == decisionRule) { + nullable.add(1); + tokens.addAll(ll1.LOOK(p, null)); + } + else { + for (RuleTransition rt : callByFollowState.values()) { + if (rt.target.ruleIndex == p.ruleIndex) work.add(rt.followState); + } + } + } + else { + work.add(t.target); + } + } + else { + tokens.addAll(t.label()); + } + } + } + } + + /** + * Does this configuration genuinely start via R - i.e. does its + * call chain contain an R invocation as the first consuming + * invocation of the decision? Formally: walking the stack + * segments from the top, there is a deepest segment whose rule is R + * (the outermost R invocation, since configurations reached by the + * decision's own closure can only nest R inside R's own parse), and + * every segment below it - the wrapper calls from the decision entry + * to that invocation - lies on an epsilon-only path from the + * decision (its return address is in {@link #epsilonCallSites}). + * A configuration that reached R through a token-consuming call + * site (a TRIM argument, a subscript bracket) has a non-epsilon + * segment below the R invocation and fails; so does one whose + * widening joint hides a non-epsilon entry. Merged contexts: any + * branch may establish the derivation. + */ + public boolean startsViaR(ATNConfig c, DecisionState s, int ruleR) { + Set callSites = epsilonCallSites(s, ruleR); + return segStartsViaR(c.state.ruleIndex, c.context, ruleR, callSites, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); + } + + /** Does the sub-chain from ({@code stateRule}, {@code ctx}) down + * transit R as first consumer? Deepest-first: the outermost R + * invocation is the deepest R segment on the stack, and only its + * below-path is validated (segments above it are inside R's own + * parse, its business). */ + private boolean segStartsViaR(int stateRule, PredictionContext ctx, int ruleR, + Set callSites, Set visited) { + // deepest-first: try the frames below for a deeper R segment + if (ctx != null && visited.add(ctx)) { for (int i = 0; i < ctx.size(); i++) { int rs = ctx.getReturnState(i); if (rs != PredictionContext.EMPTY_RETURN_STATE - && atn.states.get(rs).ruleIndex == ruleR) { + && segStartsViaR(atn.states.get(rs).ruleIndex, ctx.getParent(i), ruleR, callSites, visited)) { return true; } - PredictionContext p = ctx.getParent(i); - if (p != null) work.add(p); + } + } + // no deeper R segment validates: is THIS the outermost R segment? + if (stateRule == ruleR) { + return allCallSitesToEmpty(ctx, callSites, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); + } + return false; + } + + private boolean allCallSitesToEmpty(PredictionContext ctx, Set callSites, + Set visited) { + if (ctx == null || ctx.isEmpty()) return true; + if (!visited.add(ctx)) return true; + for (int i = 0; i < ctx.size(); i++) { + int rs = ctx.getReturnState(i); + if (rs == PredictionContext.EMPTY_RETURN_STATE) continue; + if (callSites.contains(rs) + && allCallSitesToEmpty(ctx.getParent(i), callSites, visited)) { + return true; } } return false; } + /** + * Follow states of every rule call lying on an epsilon-only path + * from the decision entry to an R invocation (wrapper calls and the + * R-entry call itself), not descending into R. + */ + private Set epsilonCallSites(DecisionState s, int ruleR) { + String key = s.decision + ":" + ruleR; + Set sites = callSitesCache.get(key); + if (sites == null) { + sites = new HashSet(); + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + for (int i = 0; i < s.getNumberOfTransitions(); i++) work.add(s.transition(i).target); + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st) || st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + sites.add(rt.followState.stateNumber); + if (rt.target.ruleIndex != ruleR) work.add(t.target); + } + else if (t.isEpsilon()) { + work.add(t.target); + } + } + } + callSitesCache.put(key, sites); + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("CALLSITES d=%d rule=%s sites=%s%n", s.decision, + ruleR >= 0 ? "?" : "?", sites); + } + } + return sites; + } + /** * Rules invocable from the decision via epsilon-only descents, in * BFS order (shallowest shared rules first). @@ -168,6 +381,36 @@ else if (t.isEpsilon()) { return rules; } + /** The source state of the first R-call found on an epsilon-only + * descent from the decision whose first transition is the call - + * the shape of call-site the error recovery requires (it re-reads + * the invoking state's first transition as the invoking call). */ + private int firstCallSite(DecisionState s, int ruleR) { + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + for (int i = 0; i < s.getNumberOfTransitions(); i++) work.add(s.transition(i).target); + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st) || st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + if (((RuleTransition)t).target.ruleIndex == ruleR) { + if (st.transition(0) == t) return st.stateNumber; + work.add(t.target); + } + else { + work.add(t.target); + } + } + else if (t.isEpsilon()) { + work.add(t.target); + } + } + } + return s.stateNumber; + } + /** * Does alternative {@code alt} descend to an R invocation with zero * token consumption (on some path)? diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index 8d83a03855..55ed5e8989 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -204,8 +204,20 @@ public Choice getChoiceBlock(BlockAST blkAST, List alts, Gramma c = getLL1ChoiceBlock(blkAST, alts); } else if ( hasStaticDFA(decision) ) { - c = new DFAAltBlock(this, blkAST, alts); - c.tableCanDefer = staticDFACanDefer(decision); + DFAAltBlock dfaBlock = new DFAAltBlock(this, blkAST, alts); + dfaBlock.tableCanDefer = staticDFACanDefer(decision); + org.antlr.v4.analysis.SharedDescentAnalyzer.Plan descentPlan = + g.staticDescentPlans != null ? g.staticDescentPlans.get(decision) : null; + org.antlr.v4.codegen.model.DescentAltBlock descentBlock = + descentPlan != null && gen.getTarget().supportsFactoredAltMask() + && hasDescentMask(decision, descentPlan) + ? buildDescentAltBlock(dfaBlock, descentPlan) : null; + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("DESCENT-CODEGEN decision=%d plan=%s block=%s%n", + decision, descentPlan == null ? "null" : descentPlan.groups.size(), + descentBlock != null); + } + c = descentBlock != null ? descentBlock : dfaBlock; } else { c = getComplexChoiceBlock(blkAST, alts); @@ -282,6 +294,76 @@ protected boolean staticDFACanDefer(int decision) { return dfa != null && (dfa.hasEscapes() || dfa.hasMasks()); } + /** Does the decision's emitted table contain a mask-accept covered + * by one of the plan's descent groups? The block is only worth + * emitting then; a plan whose groups never fire in the table must + * not introduce adaptive widen paths into an otherwise fully + * static parser. */ + protected boolean hasDescentMask(int decision, + org.antlr.v4.analysis.SharedDescentAnalyzer.Plan plan) { + org.antlr.v4.analysis.StaticDFA dfa = + g.staticDecisionDFAs != null ? g.staticDecisionDFAs.get(decision) : null; + if (dfa == null) return false; + for (long m : dfa.acceptMasks) { + if (m == 0) continue; + for (org.antlr.v4.analysis.SharedDescentAnalyzer.Group grp : plan.groups) { + if (grp.codegenable && m == altBitsOf(grp.alts)) return true; + } + } + return false; + } + + /** + * Build the {@link org.antlr.v4.codegen.model.DescentAltBlock} for a + * decision with a validated shared-descent plan, or null when no + * group is codegenable (the ordinary DFAAltBlock then stays; its + * mask-accept states defer to adaptivePredict). Only for targets + * with mask codegen. + */ + protected org.antlr.v4.codegen.model.DescentAltBlock buildDescentAltBlock( + DFAAltBlock base, org.antlr.v4.analysis.SharedDescentAnalyzer.Plan plan) { + org.antlr.v4.codegen.model.DescentAltBlock block = + new org.antlr.v4.codegen.model.DescentAltBlock(base); + boolean any = false; + for (org.antlr.v4.analysis.SharedDescentAnalyzer.Group grp : plan.groups) { + if (!grp.codegenable) continue; + String defaultBit = grp.defaultAlt != 0 + ? "0x" + Long.toHexString(1L << (grp.defaultAlt-1)) : null; + org.antlr.v4.codegen.model.DescentGroup group = + new org.antlr.v4.codegen.model.DescentGroup(this, base.decision, altBitsOf(grp.alts), + gen.getTarget().escapeIfNeeded(g.getRule(grp.rule).name), defaultBit, + grp.callSiteState); + for (java.util.Map.Entry e + : grp.explicitArms.entrySet()) { + group.tails.add(new org.antlr.v4.codegen.model.DescentGroup.Tail( + this, tailArmKey(e.getValue()), e.getKey())); + } + block.groups.add(group); + any = true; + } + return any ? block : null; + } + + /** Group alternative bitmask (bit 1<<(alt-1) per member). */ + private static long altBitsOf(java.util.BitSet alts) { + long mask = 0; + for (int a = alts.nextSetBit(0); a >= 0; a = alts.nextSetBit(a+1)) mask |= 1L << (a-1); + return mask; + } + + /** Match-arm pattern for a token set: token-type constants joined with " | ". */ + private String tailArmKey(org.antlr.v4.runtime.misc.IntervalSet first) { + StringBuilder sb = new StringBuilder(); + org.antlr.v4.codegen.Target target = gen.getTarget(); + for (int i = 0; i < first.size(); i++) { + if (i > 0) sb.append(" | "); + int ttype = first.get(i); + sb.append(g.name).append('_') + .append(target.escapeIfNeeded(target.getTokenTypeAsTargetLabel(g, ttype))); + } + return sb.toString(); + } + /** Like getComplexEBNFBlock but driving the decision from a static DFA table. */ protected Choice getDFAEBNFBlock(GrammarAST ebnfRoot, List alts, int decision) { int ebnf = 0; diff --git a/tool/src/org/antlr/v4/codegen/model/DescentAltBlock.java b/tool/src/org/antlr/v4/codegen/model/DescentAltBlock.java new file mode 100644 index 0000000000..8e85510271 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/DescentAltBlock.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this source code is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * An alt block whose decision may accept with a shared-descent group's + * alternative mask (rule-level factoring). The runtime's + * dfa_predict_mask walker returns the set of live alternatives as a + * bitmask. Singleton masks take the ordinary alternative arms; a mask + * covering a shared-descent group takes its descent arm: speculatively + * call the group's common rule once (muted, rewound, graft removed), + * then dispatch on the post-descent lookahead to the member + * alternative's singleton arm. The prefix enumeration that exhausted + * the table's construction budget is executed once instead of being + * simulated per alternative. + */ +public class DescentAltBlock extends AltBlock { + @ModelElement public final List singletons = + new ArrayList(); + @ModelElement public final List groups = new ArrayList(); + + public DescentAltBlock(AltBlock base) { + super(base.factory, base.ast, base.alts); + this.decision = base.decision; + this.tableCanDefer = base.tableCanDefer; + this.label = base.label; + this.preamble = base.preamble; + for (int i = 0; i < base.alts.size(); i++) { + singletons.add(new FactoredAltBlock.SingletonArm(base.factory, i+1, base.alts.get(i))); + } + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/DescentGroup.java b/tool/src/org/antlr/v4/codegen/model/DescentGroup.java new file mode 100644 index 0000000000..6d5c3696f6 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/DescentGroup.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this source code is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +package org.antlr.v4.codegen.model; + +import org.antlr.v4.codegen.OutputModelFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * One shared-descent group of a {@link DescentAltBlock}: the group's + * alternative mask, the common rule's invocation (the speculative + * prefix), the tail-dispatch arms (token-type constants of each + * non-default member alternative's tail FIRST set, keyed to that + * alternative's singleton bit), and the default member's singleton bit + * (or an adaptive fallback when the dispatch is all-explicit). + */ +public class DescentGroup extends OutputModelObject { + /** One tail-dispatch arm: token-type constants -> a member's singleton bit. */ + public static class Tail extends OutputModelObject { + public final String armKey; + public final String altBit; + + public Tail(OutputModelFactory factory, String armKey, int alt) { + super(factory); + this.armKey = armKey; + this.altBit = "0x" + Long.toHexString(1L << (alt-1)); + } + } + + /** The decision this group belongs to. */ + public final int decision; + /** A valid call-site state of the common rule: the block sets the + * parser's invoking state to it before the neutral parse. */ + public final int callSiteState; + /** Match-arm key of the group's alternative mask (hex literal). */ + public final String maskKey; + /** The common rule's generated method name (the shared descent). */ + public final String ruleName; + @ModelElement public final List tails = new ArrayList(); + /** The default member's singleton bit (hex literal), or null for an + * all-explicit dispatch (the fallback widens via adaptivePredict). */ + public final String defaultBit; + + public DescentGroup(OutputModelFactory factory, int decision, long mask, String ruleName, String defaultBit, + int callSiteState) { + super(factory); + this.decision = decision; + this.maskKey = "0x" + Long.toHexString(mask); + this.ruleName = ruleName; + this.defaultBit = defaultBit; + this.callSiteState = callSiteState; + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/RuleFunction.java b/tool/src/org/antlr/v4/codegen/model/RuleFunction.java index f26ab5968d..16679512e4 100644 --- a/tool/src/org/antlr/v4/codegen/model/RuleFunction.java +++ b/tool/src/org/antlr/v4/codegen/model/RuleFunction.java @@ -34,6 +34,7 @@ public class RuleFunction extends OutputModelObject { public final String name; public final String escapedName; + public final boolean resumeTarget; public final List modifiers; public String ctxType; public final Collection ruleLabels; @@ -58,6 +59,7 @@ public RuleFunction(OutputModelFactory factory, Rule r) { super(factory); this.name = r.name; this.escapedName = factory.getGenerator().getTarget().escapeIfNeeded(r.name); + this.resumeTarget = r.resumeTarget; this.rule = r; modifiers = Utils.nodesToStrings(r.modifiers); diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index 64a42e65e6..e5c114a6c8 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -213,6 +213,12 @@ public class Grammar implements AttributeResolver { */ public Map staticFactorPlans; + /** Per-decision shared-descent plans (SharedDescentAnalyzer), populated + * with -Xstatic-dfa for decisions with at least one shared-descent + * group; drives the DescentAltBlock codegen (rule-level factoring: + * call the common rule once, dispatch at the post-descent tail). */ + public Map staticDescentPlans; + public final Tool tool; /** Token names and literal tokens like "void" are uniquely indexed. diff --git a/tool/src/org/antlr/v4/tool/Rule.java b/tool/src/org/antlr/v4/tool/Rule.java index f4c98315f6..ae7a4f1af6 100644 --- a/tool/src/org/antlr/v4/tool/Rule.java +++ b/tool/src/org/antlr/v4/tool/Rule.java @@ -53,6 +53,11 @@ public class Rule implements AttributeResolver { } public final String name; + + /** This rule is the common rule R of at least one shared-descent + * group (see SharedDescentAnalyzer): its generated function carries + * the resume_take short-circuit hook. */ + public boolean resumeTarget; public List modifiers; public RuleAST ast; From b200fdfa094fb7e4377c29e61ce54f19d34499b9 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Wed, 22 Jul 2026 12:50:31 -0400 Subject: [PATCH 25/48] Unified factoring analysis: leading-token prefixes + shared descent in one model Extends the shared-descent machinery into a unified factor analysis: a group is a shared leading token prefix (zero or more tokens) plus a shared first-consuming rule R - the prefix-factor analyzer's token prefixes and the shared-descent analyzer's rule descents as one model ('(' expression for the paren family is a one-token prefix; wrapper chains like selectItem->...->primaryExpression are the zero-token case). The factored block matches the prefix tokens, parses R once, then resume mode re-descends: the re-descent re-matches the prefix naturally and short-circuits R with the stored node. So the nested parenthesized family (the last escape family at Trino d=316 and its ParenExpr witness) is statically resolved: the common prefix case of '(' query ')' vs '(' expression ')' is decided by trying R and dispatching on the tail, and deep nesting parses through with one parse per level, no speculation, no exponential paths. Analysis: one DFS per alternative yields every (rule, prefix) candidate, clustered by (rule, identical prefix); blockAlts widen the mask to prefix-sharing non-members (they fall through to the widen arm, accepted without conflict resolution); the first-consumer proof is boundary-aware (wrapper segments validated down to the R-call follow state, the prefix consumed below); and a precise ambiguity disjointness check (a collision is fatal only when a token completes both a non-member alternative and R and min-alt would prefer the non-member - ParenExpr's '(ID)' collision is harmless since parens wins min-alt, and Trino's d=316 group passes since '(TABLE)' cannot complete a query). Codegen: the descent block arm fires for any multi-alt subset of a group's block alternatives; the block is emitted only when the table actually carries a group's mask (shared SharedDescentAnalyzer. hasDescentMask helper, also used to let the inline factor executor yield); start_resume/discard_graft un-match the block's prefix tokens (the re-descent re-matches them); and the walker's returned live-set mask (not the group's bits) is what the table stores. Prefixes are capped at two tokens (real factor prefixes are one or two). Fixes caught by the battery: prefix marks must be taken before the prefix matches (the re-descent re-matches them); the R-call branch of the path search is itself the reach (no self-descent); mandatoryTail must start post-prefix; and the errorful path must discard the block's prefix children too. Battery: cargo 11 suites (paren corners now include (((((x))))), ((((((1, 2)))))), ((((SELECT 1)))) deep nesting), tool-testsuite 694, runtime-testsuite rust.** 707, 3202-query corpus (2 known '::' error-path divergences), 7/7 witnesses, perf unchanged. Escapes: ExprLoops 27, Trino 1119, Bigquery 615, Databricks 3881, Duckdb 4123, Redshift 2811, Snowflake 3339 (Snowflake -157, Duckdb -52). Signed-off-by: Bo Lin --- runtime/Rust/src/parser.rs | 12 +- runtime/Rust/tests/gen/fuzzexprparser.rs | 8 +- runtime/Rust/tests/gen/parenexprparser.rs | 113 +++--- .../Rust/tests/paren_differential_tests.rs | 8 + .../v4/tool/templates/codegen/Rust/Rust.stg | 10 +- .../antlr/v4/analysis/DecisionClassifier.java | 20 +- .../v4/analysis/SharedDescentAnalyzer.java | 366 ++++++++++++++++-- .../v4/codegen/OutputModelController.java | 4 +- .../org/antlr/v4/codegen/ParserFactory.java | 10 +- .../antlr/v4/codegen/model/DescentGroup.java | 14 +- 10 files changed, 460 insertions(+), 105 deletions(-) diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 61d69c5c27..6a2254d04e 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -550,10 +550,13 @@ where /// adaptive engine). #[doc(hidden)] #[allow(invalid_reference_casting)] - pub fn discard_graft(&mut self, node: &'arena TreeNode<'input, 'arena, Node, TF::Tok>) { + pub fn discard_graft(&mut self, node: &'arena TreeNode<'input, 'arena, Node, TF::Tok>, prefix_len: usize) { if self.build_parse_trees { if let Some(parent) = node.get_parent() { unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); + for _ in 0..prefix_len { + unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); + } } } } @@ -580,12 +583,19 @@ where node: &'arena TreeNode<'input, 'arena, Node, TF::Tok>, rule: usize, prefix_pos: isize, + prefix_len: usize, ) { let tail_pos = self.input.index(); if self.build_parse_trees { if let Some(parent) = node.get_parent() { self.set_current_ctx(Some(parent)); + // un-graft the neutral-parse node and the prefix tokens + // the block matched for it: the re-descent re-matches + // them all naturally unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); + for _ in 0..prefix_len { + unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); + } } } self.resume_node = Some((node, rule, tail_pos)); diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index 3332b0301e..6246733d27 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -463,7 +463,7 @@ where match { let _m = recog.base.dfa_predict_mask(2)?; match _m { 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), - x if x == 0x3 && !recog.base.resume_active() => { + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() => { let _pos0 = recog.input.index(); recog.base.set_state(25); recog.base.begin_mute(); @@ -480,7 +480,7 @@ where if recog.base.syntax_error_count() != _errs { // errorful neutral parse: throw its result away and // defer (muted, so no spurious reports escaped) - recog.base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node)); + recog.base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node), 0); recog.input.seek(_pos0); 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) } @@ -491,13 +491,13 @@ where FuzzExpr_T__2 => 0x1, _ => 0x2 }; - recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e, _pos0); + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e, _pos0, 0); _tailbit } }, } }, - 0x3 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), m => m, } } { x if x == 0x1 =>{ diff --git a/runtime/Rust/tests/gen/parenexprparser.rs b/runtime/Rust/tests/gen/parenexprparser.rs index 39a34f0749..5a8172bfe9 100644 --- a/runtime/Rust/tests/gen/parenexprparser.rs +++ b/runtime/Rust/tests/gen/parenexprparser.rs @@ -1172,12 +1172,20 @@ where { #[inline] pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - self.e_rec(0) + { + let recog = &mut *self; + if let Some(_node) = recog.base.resume_take(RULE_e) { + return Ok(_node.as_rule_context().unwrap()); + } + }self.e_rec(0) } fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { dbt_antlr4::maybe_grow_stack!({ let recog = self; + if let Some(_node) = recog.base.resume_take(RULE_e) { + return Ok(_node.as_rule_context().unwrap()); + } let _parentctx = recog.base.take_ctx(); let _parentState = recog.base.get_state(); recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; @@ -1191,7 +1199,49 @@ where { recog.base.set_state(32); recog.err_handler.sync(&mut recog.base)?; - match { let _m = recog.base.dfa_predict_mask(1)?; if _m == 0 { 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) } else { _m } } { + match { let _m = recog.base.dfa_predict_mask(1)?; + match _m { + 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() => { + let _pos0 = recog.input.index(); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + + recog.base.set_state(13); + recog.base.begin_mute(); + let _errs = recog.base.syntax_error_count(); + match recog.e() { + Err(e) if !e.is_recoverable() => return Err(e), + Err(_) => { + recog.base.end_mute(); + recog.input.seek(_pos0); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + recog.base.end_mute(); + if recog.base.syntax_error_count() != _errs { + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + recog.base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node), 1); + recog.input.seek(_pos0); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream; + // only then rewind into resume mode + let _tailbit = match recog.input.la(1) { + ParenExpr_T__1 => 0x4, + ParenExpr_T__2 => 0x8, + _ => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) + }; + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e, _pos0, 1); + _tailbit + } + }, + } + }, + x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), + m => m, + } } { x if x == 0x1 =>{ { recog.base.with_mut_ctx(|ctx| { NumContextExt::copy_from(ctx); }); @@ -1276,52 +1326,6 @@ where recog.base.set_state(31); recog.e_rec(3)?; } - } - x if x == 0xc =>{ - { - recog.base.set_state(12); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(57); - recog.e_rec(0)?; - } - match recog.input.la(1) { - ParenExpr_T__1 =>{ - { - recog.base.with_mut_ctx(|ctx| { RowConstructorContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena RowConstructorContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(16); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - loop { - { - { - recog.base.set_state(14); - recog.base.match_token(ParenExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(15); - recog.e_rec(0)?; - } - } - recog.base.set_state(18); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if !(_la==ParenExpr_T__1) {break} - } - recog.base.set_state(20); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - } - }, - ParenExpr_T__2 =>{ - { - recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(24); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - } - } - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } } _ => {} } @@ -1864,7 +1868,7 @@ where // the serialized ATN is followed by 5 static SLL prediction tables (-Xstatic-dfa): // decision 3: precedence-dispatched over cutoffs [1, 2], tables [2 3 4] -// decision 1: LL(k), k=5, 34 states, 4 adaptive escapes, 12 mask accepts +// decision 1: LL(k), k=5, 34 states, 2 adaptive escapes, 14 mask accepts // decision 2: LL(k), k=1, 3 states // table 2 (decision 3): LL(k), k=1, 5 states // table 3 (decision 3): LL(k), k=1, 6 states @@ -1872,7 +1876,7 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); -static _serializedATN: [&'static str; 16] = [ +static _serializedATN: [&'static str; 17] = [ "CAIWdAQADgAEAg4CBAQOBAIAAgACAAICAgICAgICAgICAgICCAIiEAIWAhgCJAICAgICAgICAgICAgIC", "AgICAgICAgICAgYCQhACAgICAgICAgICAgICCgJSEAIUAhgCWBICAgQCBAIEAgQCBAIEAgQGBGoQBAIE", "BgJwEAICAgACBAYABAgABAIACgwEAAgIDg6AAQAMAgAAAARAAgAAAAhoAgAAAAwOBgQCAA4QCgAAAhAC", @@ -1882,11 +1886,12 @@ static _serializedATN: [&'static str; 16] = [ "AgAAAEJUAgAAAERGFAQAAEZIDgAAAEhSBgQCBkpMFAIAAExODgIAAE5SBgQCBFBEAgAAAFBKAgAAAFJY", "AgAAAFRQAgAAAFRWAgAAAFYGAgAAAFhUAgAAAFpcChAAAFxqChIAAF5qChIAAGBiCgIAAGJkBggEAGRm", "CgYAAGZqAgAAAGhaAgAAAGheAgAAAGhgAgAAAGoKAgAAAG4gAgAAAG4wAgAAAHJuBgQCAAwkQFBUaG4M", - "CggCRPYBAAAMBAIAAAoAAAEAAAAAAAAGAQAIAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "CggCRPYBAAAMBAIAAAoAAAAAAAAAAAAGAQAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAGDY2NjZUZmZ4igGKAZwBogG0AcYB5AHkAeQB5AH2AfYB9gH2AfYB9gH2AfYB", "9gH2AfYB9gH2AfYB9gECAgIICAQSEgYUFAgCAgoICAwQEA4SEhAUFBICAhQICBYQEBgSEhoUFBwCAh4I", "CCASFBIEBCIGBiQIDiYEBCIGBigIDiYCAioICCASFBwSEiwEBC4GBjAIDjIEBC4GBjQIDjICAjYICCAQ", - "EDgSEjoUFDwCAj4ICEASFEIYIAQGCCoEBgguBAYIMgQGCDQEBgg2BAYIOAQGCDoEBgg8BAYIPgQGCEAE", - "BghCBAYIBAYSAAQCAAAAABISEggIAgoMBA4OAgABChgABAQEAgQAAAAAABgYGBgYAQECBAQEBgYGCA4I", - "AAEMJAAEBAQEAgQAAAAAAAAkJCQkJCQBAQIEBAQGBgYICAgKDAoODggAAQIABAAAAAACBgQCBAQGCA==" + "EDgSEjoUFDwCAj4ICEASFEIcFAYGCAogBAYIKgQGCCwGBggKLgQGCDIEBgg0BAYINgQGCDgEBgg6BAYI", + "PAQGCD4EBghABAYIQgQGCAQGEgAEAgAAAAASEhIICAIKDAQODgIAAQoYAAQEBAIEAAAAAAAYGBgYGAEB", + "AgQEBAYGBggOCAABDCQABAQEBAIEAAAAAAAAJCQkJCQkAQECBAQEBgYGCAgICgwKDg4IAAECAAQAAAAA", + "AgYEAgQEBgg=" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/paren_differential_tests.rs b/runtime/Rust/tests/paren_differential_tests.rs index 63cef3cd55..5d81036b34 100644 --- a/runtime/Rust/tests/paren_differential_tests.rs +++ b/runtime/Rust/tests/paren_differential_tests.rs @@ -81,6 +81,13 @@ const CORNERS: &[&str] = &[ "(SELECT t)", "(t)", "((SELECT t))", + // deep nesting: the subquery reading stays alive until the + // innermost content is seen; the unified block parses through + "((((1))))", + "(((((x)))))", + "((((((1, 2))))))", + "((((SELECT 1))))", + "((((SELECT t))))", // the tail decision inside operators "1 + (2 * 3)", "(1 + 2) * (3 + 4)", @@ -110,3 +117,4 @@ fn paren_family_corners_agree() { check(corner); } } + diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index 12c3639d3c..be1ac64aec 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -857,8 +857,10 @@ descentMaskPredict(choice, groups) ::= << >> DescentGroup(g, tails) ::= << - x if x == && !.base.resume_active() => { + x if x != 0 && (x & !) == 0 && (x & (x-1)) != 0 && !.base.resume_active() => { let _pos0 = .input.index(); +.base.match_token(,&mut .err_handler)?; +}> .base.set_state(); .base.begin_mute(); let _errs = .base.syntax_error_count(); @@ -874,7 +876,7 @@ DescentGroup(g, tails) ::= << if .base.syntax_error_count() != _errs { // errorful neutral parse: throw its result away and // defer (muted, so no spurious reports escaped) - .base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node)); + .base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node), ); .input.seek(_pos0); 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) } @@ -885,13 +887,13 @@ DescentGroup(g, tails) ::= << _ => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) }; - .base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_, _pos0); + .base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_, _pos0, ); _tailbit } }, } }, - => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), + x if x != 0 && (x & !) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), >> Tail(t) ::= " => ," diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 245a98c7b6..4a1076cf53 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -501,10 +501,14 @@ public Result(DecisionState decisionState) { /** The shared-descent plan of the decision being classified. */ protected SharedDescentAnalyzer.Plan currentDescentPlan; - /** Do all live configurations of this state genuinely start via R? */ - protected boolean allStartViaR(Set configs, DecisionState s, int ruleR) { + /** Do all live configurations of this state genuinely start via the + * group's rule (first-consumer proof, prefix-aware)? Configurations + * of non-member alternatives are exempt: they fall through to the + * block's widen arm, which defers them to adaptivePredict. */ + protected boolean allStartViaR(Set configs, DecisionState s, + SharedDescentAnalyzer.Group grp) { for (ATNConfig c : configs) { - if (!descentAnalyzer().startsViaR(c, s, ruleR)) return false; + if (grp.alts.get(c.alt) && !descentAnalyzer().startsViaR(c, s, grp)) return false; } return true; } @@ -1419,14 +1423,13 @@ else if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { } else { SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null - && !currentFactorPlan.hasGroups() ? currentDescentPlan.groupCovering(alts) : null; - if (descentGroup != null && allStartViaR(configs, s, descentGroup.rule)) { + if (descentGroup != null && allStartViaR(configs, s, descentGroup)) { res.descentMaskStates++; res.approxConflicts.remove(conflicting); res.contextSensitiveConflicts.remove(conflicting); res.exactAmbigConflicts.add(conflicting); - acceptMasks.set(d, altBits(descentGroup.alts)); + acceptMasks.set(d, altBits(alts)); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { System.err.printf("DESCENT-MASK d=%d state=%d rule=%s alts=%s%n", s.decision, d, g.getRule(descentGroup.rule).name, descentGroup.alts); @@ -1480,11 +1483,10 @@ else if (abortOnUntrustedConflict) { } else { SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null - && !currentFactorPlan.hasGroups() ? currentDescentPlan.groupCovering(alts) : null; - if (descentGroup != null && allStartViaR(configs, s, descentGroup.rule)) { + if (descentGroup != null && allStartViaR(configs, s, descentGroup)) { res.descentMaskStates++; - acceptMasks.set(d, altBits(descentGroup.alts)); + acceptMasks.set(d, altBits(alts)); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { System.err.printf("DESCENT-MASK d=%d state=%d rule=%s alts=%s%n", s.decision, d, g.getRule(descentGroup.rule).name, descentGroup.alts); diff --git a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java index a8acaeaa40..8a7f6e0c83 100644 --- a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java +++ b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java @@ -23,6 +23,7 @@ import java.util.BitSet; import java.util.Deque; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -79,7 +80,20 @@ public Group(int rule, BitSet alts) { * generated block sets the parser's invoking state to it before * calling the common rule, so error recovery sees a proper * call frame). */ - public int callSiteState; + public int callSiteState = -1; + /** Leading token types shared by every member alternative + * before the epsilon descent to {@link #rule} (empty for a + * pure zero-token descent). */ + public final List prefixTokens = new ArrayList(); + /** The block's full mask: member alternatives plus prefix-sharing + * non-members (they fall through to the widen arm, which defers + * to adaptivePredict - so their conflicts never need resolving, + * but their states are accepted). */ + public final BitSet blockAlts = new BitSet(); + /** The R-call follow states of the member alternatives: the + * prefix-side boundary of the first-consumer proof (frames + * below the R segment are validated only down to these). */ + public final Set boundaryStates = new HashSet(); } /** Per-decision plan: the shared-descent groups of the decision. */ @@ -88,10 +102,10 @@ public static class Plan { public boolean hasGroups() { return !groups.isEmpty(); } - /** The group whose member alternatives cover {@code live}, or null. */ + /** The group whose block alternatives cover {@code live}, or null. */ public Group groupCovering(BitSet live) { for (Group grp : groups) { - BitSet covered = (BitSet)grp.alts.clone(); + BitSet covered = (BitSet)(grp.blockAlts.isEmpty() ? grp.alts.clone() : grp.blockAlts.clone()); covered.and(live); if (covered.equals(live)) return grp; } @@ -114,25 +128,194 @@ public SharedDescentAnalyzer(Grammar g, ATN atn, Map ca /** Build the decision's shared-descent plan. */ public Plan buildPlan(DecisionState s) { Plan plan = new Plan(); - for (int r : candidates(s)) { - BitSet members = new BitSet(); + // one DFS per alternative yields every (rule, prefix) candidate; + // cluster alternatives sharing the same (rule, prefixTokens) + Map byKey = new LinkedHashMap(); + Map> pathsByKey = new LinkedHashMap>(); + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { for (int a = 1; a <= s.getNumberOfTransitions(); a++) { - if (altStartsViaR(s, a, r)) members.set(a); + for (AltPath p : altPaths(s, a)) { + System.err.printf("CAND d=%d alt=%d rule=%s prefix=%s%n", s.decision, a, + g.getRule(p.rule).name, p.tokens); + } + } + } + for (int a = 1; a <= s.getNumberOfTransitions(); a++) { + for (AltPath p : altPaths(s, a)) { + String key = p.rule + "|" + p.tokens; + byKey.computeIfAbsent(key, k -> new BitSet()).set(a); + pathsByKey.computeIfAbsent(key, k -> new ArrayList()).add(p); + } + } + for (Map.Entry e : byKey.entrySet()) { + if (e.getValue().cardinality() < 2) continue; + List paths = pathsByKey.get(e.getKey()); + AltPath first = paths.get(0); + Group grp = new Group(first.rule, e.getValue()); + grp.prefixTokens.addAll(first.tokens); + for (AltPath p : paths) { + if (grp.callSiteState < 0) grp.callSiteState = p.callSite; + grp.boundaryStates.add(p.boundary); + } + analyzeDispatch(s, grp); + boolean dj = disjointOk(s, grp); + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("DISPATCH d=%d rule=%s alts=%s default=%d arms=%s disjoint=%s%n", + s.decision, g.getRule(grp.rule).name, grp.alts, grp.defaultAlt, grp.explicitArms, dj); } - if (members.cardinality() >= 2) { - Group grp = new Group(r, members); - grp.callSiteState = firstCallSite(s, r); - analyzeDispatch(s, grp); - plan.groups.add(grp); - if ("descent".equals(System.getProperty("antlr.dfa.debug")) && grp.codegenable) { - System.err.printf("DESCENT-PLAN d=%d rule=%s alts=%s default=%d arms=%s%n", - s.decision, g.getRule(r).name, members, grp.defaultAlt, grp.explicitArms); + if (grp.codegenable && !dj) grp.codegenable = false; + // the block's mask widens to prefix-sharing non-members (they + // fall through to the widen arm, so their states are accepted + // without any conflict resolution of their own) + if (grp.codegenable && !grp.prefixTokens.isEmpty()) { + for (int a = 1; a <= s.getNumberOfTransitions(); a++) { + if (!grp.alts.get(a) && postPrefixState(s, a, grp.prefixTokens) != null) { + grp.blockAlts.set(a); + } } } + grp.blockAlts.or(grp.alts); + plan.groups.add(grp); + if ("descent".equals(System.getProperty("antlr.dfa.debug")) && grp.codegenable) { + System.err.printf("DESCENT-PLAN d=%d rule=%s prefix=%s alts=%s default=%d arms=%s%n", + s.decision, g.getRule(grp.rule).name, grp.prefixTokens, grp.alts, grp.defaultAlt, grp.explicitArms); + } } return plan; } + /** + * The ambiguity disjointness check for an expression-first + * dispatch: some non-member alternative sharing the prefix could + * also complete with the same tail. That happens exactly when a + * single token completes both the non-member alternative and R + * itself (e.g. {@code (TABLE)} as a parenthesized expression vs as + * a query): then a clean R parse with that tail is not unique to + * the member and the group must be deferred. The check is precise: + * for every content-first token of every prefix-sharing non-member + * alternative, require that it cannot complete BOTH that + * alternative and R. + */ + private boolean disjointOk(DecisionState s, Group grp) { + LL1Analyzer ll1 = new LL1Analyzer(atn); + for (int a = 1; a <= s.getNumberOfTransitions(); a++) { + if (grp.alts.get(a)) continue; + ATNState post = postPrefixState(s, a, grp.prefixTokens); + if (post == null) continue; // does not share the prefix: irrelevant + for (int t : ll1.LOOK(post, null).toArray()) { + if (t <= 0) continue; + boolean cr = canBeExactly(atn.ruleToStartState[grp.rule], t); + boolean ca = canBeExactly(post, t); + // a genuine collision is fatal only when the runtime's + // min-alt resolution would prefer the non-member over + // every member of the group + if (cr && ca && a < grp.alts.nextSetBit(0)) { + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("DISJOINT-FAIL d=%d alt=%d token=%d%n", s.decision, a, t); + } + return false; + } + } + } + return true; + } + + /** The state of alternative {@code alt} after the exact prefix + * token sequence (epsilon + those tokens in order), or null when + * the alternative does not begin with the prefix. */ + private ATNState postPrefixState(DecisionState s, int alt, List prefixTokens) { + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + work.add(new Object[]{s.transition(alt-1).target, 0}); + while (!work.isEmpty()) { + Object[] item = work.poll(); + ATNState st = (ATNState)item[0]; + int k = (Integer)item[1]; + String key = st.stateNumber + ":" + k; + if (!seen.add(key) || st instanceof RuleStopState) continue; + if (k == prefixTokens.size()) return st; + int want = prefixTokens.get(k); + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + work.add(new Object[]{t.target, k}); + work.add(new Object[]{((RuleTransition)t).followState, k}); + } + else if (t.isEpsilon()) { + work.add(new Object[]{t.target, k}); + } + else if (t.label() != null && t.label().contains(want)) { + work.add(new Object[]{t.target, k+1}); + } + } + } + return null; + } + + /** Can the language from {@code start} be exactly token {@code t} + * (consume {@code t}, then reach a rule stop with only epsilon + * steps)? */ + private boolean canBeExactly(ATNState start, int t) { + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + work.add(new Object[]{start, Boolean.FALSE}); + while (!work.isEmpty()) { + Object[] item = work.poll(); + ATNState st = (ATNState)item[0]; + boolean consumed = (Boolean)item[1]; + String key = st.stateNumber + ":" + consumed; + if (!seen.add(key)) continue; + if (st instanceof RuleStopState) { + if (consumed) return true; + continue; + } + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition tr = st.transition(i); + if (tr instanceof RuleTransition) { + // descending into a callee stays epsilon only when its + // interior is token-free: in the consumed phase its + // token transitions are pruned below, leaving only the + // nullable paths + work.add(new Object[]{tr.target, consumed}); + work.add(new Object[]{((RuleTransition)tr).followState, consumed}); + } + else if (tr.isEpsilon()) { + work.add(new Object[]{tr.target, consumed}); + } + else if (!consumed && tr.label() != null && tr.label().contains(t)) { + work.add(new Object[]{tr.target, Boolean.TRUE}); + } + // any other token consumption breaks exactness + } + } + return false; + } + + /** + * Does the decision's emitted table contain a mask-accept covered + * by one of the plan's descent groups (any multi-alt subset of a + * group's block alternatives)? The block is only worth emitting + * then; a plan whose groups never fire in the table must not + * introduce adaptive widen paths into an otherwise fully static + * parser. + */ + public static boolean hasDescentMask(Grammar g, int decision) { + StaticDFA dfa = g.staticDecisionDFAs != null ? g.staticDecisionDFAs.get(decision) : null; + Plan plan = g.staticDescentPlans != null ? g.staticDescentPlans.get(decision) : null; + if (dfa == null || plan == null) return false; + for (long m : dfa.acceptMasks) { + if (m == 0 || (m & (m-1)) == 0) continue; // singletons take ordinary arms + for (Group grp : plan.groups) { + if (!grp.codegenable) continue; + BitSet cover = grp.blockAlts.isEmpty() ? grp.alts : grp.blockAlts; + long bits = 0; + for (int a = cover.nextSetBit(0); a >= 0; a = cover.nextSetBit(a+1)) bits |= 1L << (a-1); + if ((m & ~bits) == 0) return true; + } + } + return false; + } + /** * The dispatch analysis of one group: every member alt's mandatory * continuation after R (its FIRST tokens, FOLLOW tokens included iff @@ -147,7 +330,12 @@ private void analyzeDispatch(DecisionState s, Group grp) { Set nullable = new HashSet(); for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { Set nul = new HashSet(); - IntervalSet t = mandatoryTail(s, a, grp.rule, ll1, nul); + ATNState start = grp.prefixTokens.isEmpty() + ? s.transition(a-1).target + : postPrefixState(s, a, grp.prefixTokens); + IntervalSet t = start != null + ? mandatoryTailFrom(s, a, grp.rule, ll1, nul, start) + : new IntervalSet(); mandatory.put(a, t); // an empty mandatory tail is a degenerate continuation: the // alternative completes with no discriminating token, so it @@ -190,11 +378,19 @@ private void analyzeDispatch(DecisionState s, Group grp) { */ private IntervalSet mandatoryTail(DecisionState s, int alt, int ruleR, LL1Analyzer ll1, Set nullable) { + return mandatoryTailFrom(s, alt, ruleR, ll1, nullable, s.transition(alt-1).target); + } + + /** Variant of {@link #mandatoryTail} starting from the post-prefix + * state of the alternative (prefix groups: the tail lies after the + * shared prefix tokens). */ + private IntervalSet mandatoryTailFrom(DecisionState s, int alt, int ruleR, LL1Analyzer ll1, + Set nullable, ATNState startState) { IntervalSet tokens = new IntervalSet(); Set calls = new HashSet(); Set seen = new HashSet(); Deque work = new ArrayDeque(); - work.add(s.transition(alt-1).target); + work.add(startState); while (!work.isEmpty()) { ATNState st = work.poll(); if (!seen.add(st) || st instanceof RuleStopState) continue; @@ -269,7 +465,18 @@ else if (t.isEpsilon()) { */ public boolean startsViaR(ATNConfig c, DecisionState s, int ruleR) { Set callSites = epsilonCallSites(s, ruleR); - return segStartsViaR(c.state.ruleIndex, c.context, ruleR, callSites, + return segStartsViaR(c.state.ruleIndex, c.context, ruleR, callSites, null, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); + } + + /** First-consumer proof for a group with a leading token prefix: + * every wrapper segment below the outermost R segment must lie on + * the epsilon descent from the decision, down to a boundary frame + * (an R-call follow state of a member alternative - the prefix is + * consumed below it and needs no validation). */ + public boolean startsViaR(ATNConfig c, DecisionState s, Group grp) { + Set callSites = epsilonCallSites(s, grp); + return segStartsViaR(c.state.ruleIndex, c.context, grp.rule, callSites, grp.boundaryStates, java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); } @@ -279,40 +486,85 @@ public boolean startsViaR(ATNConfig c, DecisionState s, int ruleR) { * below-path is validated (segments above it are inside R's own * parse, its business). */ private boolean segStartsViaR(int stateRule, PredictionContext ctx, int ruleR, - Set callSites, Set visited) { + Set callSites, Set boundary, Set visited) { // deepest-first: try the frames below for a deeper R segment if (ctx != null && visited.add(ctx)) { for (int i = 0; i < ctx.size(); i++) { int rs = ctx.getReturnState(i); if (rs != PredictionContext.EMPTY_RETURN_STATE - && segStartsViaR(atn.states.get(rs).ruleIndex, ctx.getParent(i), ruleR, callSites, visited)) { + && segStartsViaR(atn.states.get(rs).ruleIndex, ctx.getParent(i), ruleR, callSites, boundary, visited)) { return true; } } } // no deeper R segment validates: is THIS the outermost R segment? if (stateRule == ruleR) { - return allCallSitesToEmpty(ctx, callSites, + return allCallSitesToBoundary(ctx, callSites, boundary, java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); } return false; } - private boolean allCallSitesToEmpty(PredictionContext ctx, Set callSites, - Set visited) { + /** Every wrapper segment below the R segment lies on the epsilon + * descent (in {@code callSites}), down to a boundary frame or the + * chain end. */ + private boolean allCallSitesToBoundary(PredictionContext ctx, Set callSites, + Set boundary, Set visited) { if (ctx == null || ctx.isEmpty()) return true; if (!visited.add(ctx)) return true; for (int i = 0; i < ctx.size(); i++) { int rs = ctx.getReturnState(i); if (rs == PredictionContext.EMPTY_RETURN_STATE) continue; + if (boundary != null && boundary.contains(rs)) return true; if (callSites.contains(rs) - && allCallSitesToEmpty(ctx.getParent(i), callSites, visited)) { + && allCallSitesToBoundary(ctx.getParent(i), callSites, boundary, visited)) { return true; } } return false; } + /** Group-aware call-site computation: epsilon paths from the + * descent start states (the member alternatives' post-prefix R-call + * source states, or the decision's alternative starts when the + * prefix is empty) to the group's rule. */ + private Set epsilonCallSites(DecisionState s, Group grp) { + String key = s.decision + ":" + grp.rule + ":" + grp.prefixTokens.hashCode(); + Set sites = callSitesCache.get(key); + if (sites == null) { + sites = new HashSet(); + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + if (grp.prefixTokens.isEmpty()) { + for (int i = 0; i < s.getNumberOfTransitions(); i++) work.add(s.transition(i).target); + } + else { + for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { + // the member call sites are the post-prefix R-call + // source states; the descent begins there + work.add(atn.states.get(grp.callSiteState)); + } + } + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st) || st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + sites.add(rt.followState.stateNumber); + if (rt.target.ruleIndex != grp.rule) work.add(t.target); + } + else if (t.isEpsilon()) { + work.add(t.target); + } + } + } + callSitesCache.put(key, sites); + } + return sites; + } + /** * Follow states of every rule call lying on an epsilon-only path * from the decision entry to an R invocation (wrapper calls and the @@ -415,10 +667,72 @@ else if (t.isEpsilon()) { * Does alternative {@code alt} descend to an R invocation with zero * token consumption (on some path)? */ - private boolean altStartsViaR(DecisionState s, int alt, int ruleR) { - Set seen = new HashSet(); + /** The path of one alternative to R: the leading token sequence + * consumed before the (epsilon) descent to R, the R-call's source + * state ({@link #callSite}), and the R-call's follow state + * ({@link #boundary} - the prefix-side end of the first-consumer + * proof). */ + private static final class AltPath { + final List tokens = new ArrayList(); + int rule = -1; + int callSite = -1; + int boundary = -1; + } + + /** + * The leading token sequence of alternative {@code alt} before it + * descends to R with zero further tokens, or null when no such path + * exists. The path shape is [tokens*] then epsilon-only to R. + */ + /** Bound on the leading token prefix considered (real factor + * prefixes are one to three tokens; longer loops are not useful + * and explode the search). */ + private static final int MAX_PREFIX_TOKENS = 2; + + private List altPaths(DecisionState s, int alt) { + List out = new ArrayList(); + Deque work = new ArrayDeque(); + work.add(new Object[]{s.transition(alt-1).target, new ArrayList(), Boolean.FALSE}); + Set seen = new HashSet(); + while (!work.isEmpty()) { + Object[] item = work.poll(); + ATNState st = (ATNState)item[0]; + @SuppressWarnings("unchecked") List tokens = (List)item[1]; + boolean inRule = (Boolean)item[2]; + String key = st.stateNumber + "|" + tokens + (inRule ? "r" : ""); + if (!seen.add(key) || st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + AltPath p = new AltPath(); + p.tokens.addAll(tokens); + p.rule = rt.target.ruleIndex; + p.callSite = st.stateNumber; + p.boundary = rt.followState.stateNumber; + out.add(p); + work.add(new Object[]{t.target, tokens, Boolean.TRUE}); + } + else if (t.isEpsilon()) { + work.add(new Object[]{t.target, tokens, inRule}); + } + else if (!inRule && t.label() != null && tokens.size() < MAX_PREFIX_TOKENS) { + for (int tok : t.label().toList()) { + List next = new ArrayList(tokens); + next.add(tok); + work.add(new Object[]{t.target, next, Boolean.FALSE}); + } + } + } + } + return out; + } + + /** Can R be reached from {@code start} following epsilon + * transitions and rule calls only (zero tokens)? */ + private boolean descendsToR(ATNState start, int ruleR, Set seen) { Deque work = new ArrayDeque(); - work.add(s.transition(alt-1).target); + work.add(start); while (!work.isEmpty()) { ATNState st = work.poll(); if (!seen.add(st) || st instanceof RuleStopState) continue; diff --git a/tool/src/org/antlr/v4/codegen/OutputModelController.java b/tool/src/org/antlr/v4/codegen/OutputModelController.java index 4b42d2b690..91c2d50921 100644 --- a/tool/src/org/antlr/v4/codegen/OutputModelController.java +++ b/tool/src/org/antlr/v4/codegen/OutputModelController.java @@ -262,7 +262,9 @@ else if (altInfo.isListLabel) { org.antlr.v4.analysis.PrefixFactorAnalyzer.Plan factorPlan = gg.staticFactorPlans != null ? gg.staticFactorPlans.get(((AltBlock)primaryStuff).decision) : null; - if (factorPlan != null) { + if (factorPlan != null + && !org.antlr.v4.analysis.SharedDescentAnalyzer.hasDescentMask( + gg, ((AltBlock)primaryStuff).decision)) { org.antlr.v4.codegen.model.FactoredAltBlock factored = buildFactoredAltBlock(r, (AltBlock)primaryStuff, factorPlan); if (factored != null) outerAlt.ops.set(0, factored); diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index 55ed5e8989..472575cd84 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -210,7 +210,7 @@ else if ( hasStaticDFA(decision) ) { g.staticDescentPlans != null ? g.staticDescentPlans.get(decision) : null; org.antlr.v4.codegen.model.DescentAltBlock descentBlock = descentPlan != null && gen.getTarget().supportsFactoredAltMask() - && hasDescentMask(decision, descentPlan) + && org.antlr.v4.analysis.SharedDescentAnalyzer.hasDescentMask(g, decision) ? buildDescentAltBlock(dfaBlock, descentPlan) : null; if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { System.err.printf("DESCENT-CODEGEN decision=%d plan=%s block=%s%n", @@ -330,9 +330,15 @@ protected org.antlr.v4.codegen.model.DescentAltBlock buildDescentAltBlock( String defaultBit = grp.defaultAlt != 0 ? "0x" + Long.toHexString(1L << (grp.defaultAlt-1)) : null; org.antlr.v4.codegen.model.DescentGroup group = - new org.antlr.v4.codegen.model.DescentGroup(this, base.decision, altBitsOf(grp.alts), + new org.antlr.v4.codegen.model.DescentGroup(this, base.decision, altBitsOf(grp.blockAlts), gen.getTarget().escapeIfNeeded(g.getRule(grp.rule).name), defaultBit, grp.callSiteState); + group.prefixLen = grp.prefixTokens.size(); + for (int t : grp.prefixTokens) { + group.prefixTokens.add( + g.name + '_' + gen.getTarget().escapeIfNeeded( + gen.getTarget().getTokenTypeAsTargetLabel(g, t))); + } for (java.util.Map.Entry e : grp.explicitArms.entrySet()) { group.tails.add(new org.antlr.v4.codegen.model.DescentGroup.Tail( diff --git a/tool/src/org/antlr/v4/codegen/model/DescentGroup.java b/tool/src/org/antlr/v4/codegen/model/DescentGroup.java index 6d5c3696f6..1cd26ad9c7 100644 --- a/tool/src/org/antlr/v4/codegen/model/DescentGroup.java +++ b/tool/src/org/antlr/v4/codegen/model/DescentGroup.java @@ -37,8 +37,14 @@ public Tail(OutputModelFactory factory, String armKey, int alt) { /** A valid call-site state of the common rule: the block sets the * parser's invoking state to it before the neutral parse. */ public final int callSiteState; - /** Match-arm key of the group's alternative mask (hex literal). */ - public final String maskKey; + /** Coverage bits of the group's block alternatives (hex literal): + * the arm fires for any multi-alt subset of this mask. */ + public final String coverBits; + /** Leading shared tokens before the common rule: token-type + * constants in match order (empty for a pure zero-token descent). */ + public final java.util.List prefixTokens = new java.util.ArrayList(); + /** prefixTokens.size(), as a template-ready property. */ + public int prefixLen; /** The common rule's generated method name (the shared descent). */ public final String ruleName; @ModelElement public final List tails = new ArrayList(); @@ -46,11 +52,11 @@ public Tail(OutputModelFactory factory, String armKey, int alt) { * all-explicit dispatch (the fallback widens via adaptivePredict). */ public final String defaultBit; - public DescentGroup(OutputModelFactory factory, int decision, long mask, String ruleName, String defaultBit, + public DescentGroup(OutputModelFactory factory, int decision, long cover, String ruleName, String defaultBit, int callSiteState) { super(factory); this.decision = decision; - this.maskKey = "0x" + Long.toHexString(mask); + this.coverBits = "0x" + Long.toHexString(cover); this.ruleName = ruleName; this.defaultBit = defaultBit; this.callSiteState = callSiteState; From e54fabb241b2de1f91f1d15d7cff443c51dc84af Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 24 Jul 2026 23:59:55 -0400 Subject: [PATCH 26/48] Shared descent: sound member/widen gates, ctx-safe neutral parse Soundness wrap-up of the unified factoring work, fixing three holes that let the static path mis-parse valid inputs (Trino TRIM from-form, parenthesized subqueries) and one tree-integrity hazard: - SharedDescentAnalyzer.firstConsumerUnique: a member alternative is admitted only when R is its unique first consuming position after the prefix (epsilon-only reachability, no tokens, no other calls, no alt end before R). The TRIM group (TRIM LPAREN (trimsSpec? ve? FROM) ve RPAREN) failed this: the body's optional trimsSpecification can consume BOTH while the neutral valueExpression parses the same token as identifier content, so the resume graft attached at the wrong place. - SharedDescentAnalyzer.widenHarmless: a prefix-sharing non-member is admitted to the block mask only when it cannot collide with the neutral-R span + tail dispatch: either every member beats it on adaptivePredict's min-alt rule, or its post-prefix FIRST set is disjoint from FIRST(R). The old unconditional widening plus the single-token disjointOk check missed multi-token span collisions: '(SELECT 1)' is both '( expression )' over a subquery and '( query )', and the tail dispatch committed to the wrong one (68/1200 paren-corpus divergences; now 0). - Rust.stg DescentGroup: the tail-default arm now rewinds to the decision start and defers to adaptivePredict without arming resume (it previously predicted from the post-R tail position, and armed resume for a body that re-parses everything, mis-grafting the neutral node at the first R call). - BaseParser.begin/end_neutral_parse saves and restores the parse context: an error unwinding out of the neutral parse left the context pointer stale (enter_rule grafts eagerly), corrupting both the tree and the following graft discard. Verified: cargo suites; tool-testsuite 694/0; runtime-testsuite rust.** 707/0; Trino static-vs-adaptive differential on Rust and Java twins over 3208 queries (only the 2 known '::' error-path divergences); TRIM from-form family and nested-paren subquery corners now agree. Trino Q1 static 2.4x adaptive. Descent mask-accept counts drop (the old counts included the unsound accepts); the widen gate itself costs 11 escape states on Trino. The chain-proof helpers (allStartViaR/startsViaR/epsilonCallSites) remain but are currently unused; re-admitting chain-descended groups soundly is future work. Signed-off-by: Bo Lin --- runtime/Rust/src/parser.rs | 205 ++++++++++++------ runtime/Rust/src/static_dfa.rs | 4 +- runtime/Rust/tests/gen/fuzzexprparser.rs | 55 ++--- runtime/Rust/tests/gen/parenexprparser.rs | 71 +++--- runtime/Rust/tests/gen/staticdfaparser.rs | 6 +- .../Rust/tests/paren_differential_tests.rs | 1 - .../v4/tool/templates/codegen/Rust/Rust.stg | 56 ++--- .../antlr/v4/analysis/DecisionClassifier.java | 25 ++- .../v4/analysis/SharedDescentAnalyzer.java | 183 +++++++++------- 9 files changed, 362 insertions(+), 244 deletions(-) diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 6a2254d04e..d1dcb2c4fd 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -19,7 +19,7 @@ use crate::rule_context::{states_stack, RuleContext as _}; use crate::token::{OwningToken, Token, TOKEN_EOF}; use crate::token_factory::TokenFactory; use crate::token_stream::TokenStream; -use crate::tree::{NodeKindType, ParseTreeListener, Tree as _, TreeNode}; +use crate::tree::{NodeKindType, ParseTreeListener, ParseTreeWalker, Tree as _, TreeNode}; use crate::utils::cell_update; use crate::vocabulary::Vocabulary; @@ -92,6 +92,12 @@ where fn set_recursion_limit(&mut self, v: u32); } +type ResumableNode<'input, 'arena, Node, TF> = ( + &'arena TreeNode<'input, 'arena, Node, >::Tok>, + usize, + isize, +); + /// Abstract base parser implementation /// /// Only meant to be instantiated by generated parsers @@ -150,10 +156,12 @@ where /// Resume-mode state of a shared-descent factoring: the parsed /// prefix context, its rule, and the stream position just past it /// (the tail); see `start_resume`. - resume_node: Option<(&'arena TreeNode<'input, 'arena, Node, TF::Tok>, usize, isize)>, - /// Error listeners muted during neutral prefix parses (stacked for - /// nesting); see `begin_mute`. - muted_error_listeners: Vec>>, + resume_node: Option>, + #[doc(hidden)] + pub resume_take_target: Option<&'arena TreeNode<'input, 'arena, Node, TF::Tok>>, + /// Mute all listeners (parse and error), counted for nesting; see + /// `begin_neutral_parse`. + muted: u32, pub arena: &'arena Arena, ext: Ext, @@ -284,20 +292,24 @@ where // todo report ructc inference issue let node = self.create_error_node(o)?; self.add_child_to_ctx(node); - for listener in &mut self.parse_listeners { - listener.visit_error_node( - node.as_error_node() - .expect("node was created as error node"), - )? + if !self.is_muted() { + for listener in &mut self.parse_listeners { + listener.visit_error_node( + node.as_error_node() + .expect("node was created as error node"), + )? + } } } else { let node = self.create_token_node(o)?; self.add_child_to_ctx(node); - for listener in &mut self.parse_listeners { - listener.visit_terminal( - node.as_terminal_node() - .expect("node was created as terminal node"), - )? + if !self.is_muted() { + for listener in &mut self.parse_listeners { + listener.visit_terminal( + node.as_terminal_node() + .expect("node was created as terminal node"), + )? + } } } } @@ -355,6 +367,11 @@ where err: Option<&ANTLRError>, ) { cell_update(&self._syntax_errors, |it| it + 1); + + if self.is_muted() { + return; + } + let offending_token: Option<&_> = match offending_token { None => Some(self.get_current_token().borrow()), Some(x) => Some(self.input.get(x).borrow()), @@ -451,7 +468,8 @@ where global_cache_threshold: 0, ctx: std::ptr::null_mut(), resume_node: None, - muted_error_listeners: Vec::new(), + resume_take_target: None, + muted: 0, build_parse_trees: true, matched_eof: false, state: -1, @@ -528,34 +546,75 @@ where self.dfa_walk(decision) } - /// Mute error listeners (the neutral prefix parse of a descent - /// block must not fire spurious reports on inputs it cannot - /// complete). Pair with [`Self::end_mute`]. + /// Set the stage for a neutral prefix parse: + /// - Mark the input stream so it can be rewound later + /// - Skip over prefix tokens (note: do NOT parse them through + /// [`Self::match_token`] at this point -- they are guaranteed to match by + /// the DFA predictor, and they will be properly parsed on the real + /// descent down) + /// - Save the current context so it can be restored later (the neutral + /// parse grafts its subtree under it, and an error unwinding out of it + /// leaves the context pointer stale) + /// - Mute all listeners (the neutral prefix parse of a descent + /// block must not fire spurious reports on inputs it cannot + /// complete). + /// + /// Pair with [`Self::end_neutral_parse`]. #[doc(hidden)] - pub fn begin_mute(&mut self) { - let el = std::mem::take(&mut self.error_listeners); - self.muted_error_listeners.push(el); + #[allow(clippy::type_complexity)] + pub fn begin_neutral_parse( + &mut self, + prefix_len: isize, + ) -> ( + isize, + isize, + i32, + Option<&'arena TreeNode<'input, 'arena, Node, TF::Tok>>, + ) { + let err_cnt = self.syntax_error_count(); + let pos0 = self.input.index(); + let mark = self.input.mark(); + let ctx = self.ctx(); + self.input.seek(pos0 + prefix_len); + self.muted += 1; + + (pos0, mark, err_cnt, ctx) } - /// Restore listeners muted by [`Self::begin_mute`]. + /// Undoes one level of [`Self::begin_neutral_parse`]: un-mutes, + /// rewinds the stream to the decision start, restores the saved + /// context, and un-grafts the neutral parse's subtree (the saved + /// context's last child). #[doc(hidden)] - pub fn end_mute(&mut self) { - if let Some(el) = self.muted_error_listeners.pop() { - self.error_listeners = el; - } + #[allow(clippy::type_complexity)] + pub fn end_neutral_parse( + &mut self, + (pos0, mark, _err_cnt, ctx): &( + isize, + isize, + i32, + Option<&'arena TreeNode<'input, 'arena, Node, TF::Tok>>, + ), + ) { + assert!(self.muted > 0); + self.muted -= 1; + self.input.seek(*pos0); + self.input.release(*mark); + self.set_current_ctx(*ctx); + self.discard_graft(); } /// Remove a grafted context from its parent's children (an errorful /// neutral parse's result is thrown away before deferring to the /// adaptive engine). #[doc(hidden)] - #[allow(invalid_reference_casting)] - pub fn discard_graft(&mut self, node: &'arena TreeNode<'input, 'arena, Node, TF::Tok>, prefix_len: usize) { + pub fn discard_graft(&mut self) { if self.build_parse_trees { - if let Some(parent) = node.get_parent() { - unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); - for _ in 0..prefix_len { - unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); + // The common rule context was parsed and attached to the current + // ctx as the last child, pop it off: + unsafe { + if let Some(ctx) = self.ctx_mut() { + ctx.remove_last_child(); } } } @@ -577,29 +636,14 @@ where /// nothing, the descent being epsilon by construction) until /// [`Self::resume_take`] short-circuits the stored rule. #[doc(hidden)] - #[allow(invalid_reference_casting)] pub fn start_resume( &mut self, node: &'arena TreeNode<'input, 'arena, Node, TF::Tok>, rule: usize, - prefix_pos: isize, - prefix_len: usize, ) { let tail_pos = self.input.index(); - if self.build_parse_trees { - if let Some(parent) = node.get_parent() { - self.set_current_ctx(Some(parent)); - // un-graft the neutral-parse node and the prefix tokens - // the block matched for it: the re-descent re-matches - // them all naturally - unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); - for _ in 0..prefix_len { - unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.remove_last_child(); - } - } - } + self.resume_node = Some((node, rule, tail_pos)); - self.input.seek(prefix_pos); } /// Is resume mode active (a nested descent block must defer to the @@ -614,27 +658,39 @@ where /// the tail position, and end resume mode. Returns None when /// inactive or the rule does not match. #[doc(hidden)] - #[allow(invalid_reference_casting)] pub fn resume_take( &mut self, rule: usize, - ) -> Option<&'arena TreeNode<'input, 'arena, Node, TF::Tok>> { + ) -> Result>, ANTLRError> { if self.resume_node.map(|(_, r, _)| r) != Some(rule) { - return None; + return Ok(None); } - let (node, _, tail_pos) = self.resume_node.take()?; + let (node, _, tail_pos) = self.resume_node.take().unwrap(); + + // Graft the stored node under the current context (the neutral parse + // created it with a generic invoking state and a wrong parent) if self.build_parse_trees { - // re-stamp the invoking state to the resuming call site (the - // neutral parse created the node with a generic one) - unsafe { &mut *(node as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.set_invoking_state(self.get_state()); - let parent = self.ctx(); - unsafe { &mut *(node as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.set_parent(parent); - if let Some(parent) = parent { - unsafe { &mut *(parent as *const TreeNode<'input, 'arena, Node, TF::Tok> as *mut TreeNode<'input, 'arena, Node, TF::Tok>) }.add_child(node); - } + self.add_child_to_ctx(node); } + let state = self.get_state(); + let parent = self.take_ctx(); + self.set_current_ctx(Some(node)); + self.with_mut_ctx(|ctx| { + ctx.set_parent(parent); + ctx.set_invoking_state(state); + }); + // Fire parser events that was muted during the neutral parse + if !self.is_muted() { + self.parse_listeners = std::mem::take(&mut self.parse_listeners) + .into_iter() + .map(|listener| ParseTreeWalker::walk(listener, node)) + .collect::, ANTLRError>>()?; + } + + self.set_current_ctx(parent); + self.input.seek(tail_pos); - Some(node) + Ok(Some(node)) } /// Abort resume mode on error unwind: restore the stream to the @@ -776,6 +832,11 @@ where } } + #[inline] + fn is_muted(&self) -> bool { + self.muted > 0 + } + #[inline] fn parent_ctx(&self) -> Option<&'arena TreeNode<'input, 'arena, Node, TF::Tok>> { self.ctx().and_then(|it| it.get_parent()) @@ -889,19 +950,23 @@ where } pub fn trigger_enter_rule_event(&mut self) -> Result<(), ANTLRError> { - let ctx = self.ctx().unwrap(); - for listener in self.parse_listeners.iter_mut() { - listener.enter_every_rule(ctx)?; - ctx.enter_rule(listener)?; + if !self.is_muted() { + let ctx = self.ctx().unwrap(); + for listener in self.parse_listeners.iter_mut() { + listener.enter_every_rule(ctx)?; + ctx.enter_rule(listener)?; + } } Ok(()) } pub fn trigger_exit_rule_event(&mut self) -> Result<(), ANTLRError> { - let ctx = self.ctx().unwrap(); - for listener in self.parse_listeners.iter_mut().rev() { - ctx.exit_rule(listener)?; - listener.exit_every_rule(ctx)?; + if !self.is_muted() { + let ctx = self.ctx().unwrap(); + for listener in self.parse_listeners.iter_mut().rev() { + ctx.exit_rule(listener)?; + listener.exit_every_rule(ctx)?; + } } Ok(()) } diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs index 2c42bda4a0..134c9643ab 100644 --- a/runtime/Rust/src/static_dfa.rs +++ b/runtime/Rust/src/static_dfa.rs @@ -196,8 +196,8 @@ impl StaticDFATables { dispatch_data.push(next()); } } - drop(next); - assert!(ints.next().is_none(), "trailing data in static DFA blob"); + + debug_assert!(ints.next().is_none(), "trailing data in static DFA blob"); Self { data, diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index 6246733d27..35ad91cb21 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -464,35 +464,45 @@ where match _m { 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() => { - let _pos0 = recog.input.index(); recog.base.set_state(25); - recog.base.begin_mute(); - let _errs = recog.base.syntax_error_count(); + let _neutral_state = recog.base.begin_neutral_parse(0); match recog.e() { - Err(e) if !e.is_recoverable() => return Err(e), + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, Err(_) => { - recog.base.end_mute(); - recog.input.seek(_pos0); + recog.base.end_neutral_parse(&_neutral_state); 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) }, Ok(_node) => { - recog.base.end_mute(); - if recog.base.syntax_error_count() != _errs { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); // errorful neutral parse: throw its result away and // defer (muted, so no spurious reports escaped) - recog.base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node), 0); - recog.input.seek(_pos0); 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) } else { - // the tail token decides on the post-prefix stream; - // only then rewind into resume mode + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything let _tailbit = match recog.input.la(1) { - FuzzExpr_T__2 => 0x1, - _ => 0x2 + FuzzExpr_T__2 => Some(0x1), + _ => Some(0x2), }; - recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e, _pos0, 0); - _tailbit + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + } } }, } @@ -863,20 +873,15 @@ where { #[inline] pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - { - let recog = &mut *self; - if let Some(_node) = recog.base.resume_take(RULE_e) { - return Ok(_node.as_rule_context().unwrap()); - } - }self.e_rec(0) + self.e_rec(0) } fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - if let Some(_node) = recog.base.resume_take(RULE_e) { + if let Some(_node) = self.base.resume_take(RULE_e)? { return Ok(_node.as_rule_context().unwrap()); } + dbt_antlr4::maybe_grow_stack!({ + let recog = self; let _parentctx = recog.base.take_ctx(); let _parentState = recog.base.get_state(); recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_e, _p)?; diff --git a/runtime/Rust/tests/gen/parenexprparser.rs b/runtime/Rust/tests/gen/parenexprparser.rs index 5a8172bfe9..34f9f30a9d 100644 --- a/runtime/Rust/tests/gen/parenexprparser.rs +++ b/runtime/Rust/tests/gen/parenexprparser.rs @@ -1172,20 +1172,15 @@ where { #[inline] pub fn e(&mut self,) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - { - let recog = &mut *self; - if let Some(_node) = recog.base.resume_take(RULE_e) { - return Ok(_node.as_rule_context().unwrap()); - } - }self.e_rec(0) + self.e_rec(0) } fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - if let Some(_node) = recog.base.resume_take(RULE_e) { + if let Some(_node) = self.base.resume_take(RULE_e)? { return Ok(_node.as_rule_context().unwrap()); } + dbt_antlr4::maybe_grow_stack!({ + let recog = self; let _parentctx = recog.base.take_ctx(); let _parentState = recog.base.get_state(); recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; @@ -1203,38 +1198,46 @@ where match _m { 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() => { - let _pos0 = recog.input.index(); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; - recog.base.set_state(13); - recog.base.begin_mute(); - let _errs = recog.base.syntax_error_count(); + let _neutral_state = recog.base.begin_neutral_parse(1); match recog.e() { - Err(e) if !e.is_recoverable() => return Err(e), + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, Err(_) => { - recog.base.end_mute(); - recog.input.seek(_pos0); + recog.base.end_neutral_parse(&_neutral_state); 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) }, Ok(_node) => { - recog.base.end_mute(); - if recog.base.syntax_error_count() != _errs { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); // errorful neutral parse: throw its result away and // defer (muted, so no spurious reports escaped) - recog.base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node), 1); - recog.input.seek(_pos0); 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) } else { - // the tail token decides on the post-prefix stream; - // only then rewind into resume mode + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything let _tailbit = match recog.input.la(1) { - ParenExpr_T__1 => 0x4, - ParenExpr_T__2 => 0x8, - _ => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) + ParenExpr_T__1 => Some(0x4), + ParenExpr_T__2 => Some(0x8), + _ => None, }; - recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e, _pos0, 1); - _tailbit + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) + } + } } }, } @@ -1868,7 +1871,7 @@ where // the serialized ATN is followed by 5 static SLL prediction tables (-Xstatic-dfa): // decision 3: precedence-dispatched over cutoffs [1, 2], tables [2 3 4] -// decision 1: LL(k), k=5, 34 states, 2 adaptive escapes, 14 mask accepts +// decision 1: LL(k), k=5, 34 states, 16 mask accepts // decision 2: LL(k), k=1, 3 states // table 2 (decision 3): LL(k), k=1, 5 states // table 3 (decision 3): LL(k), k=1, 6 states @@ -1886,12 +1889,12 @@ static _serializedATN: [&'static str; 17] = [ "AgAAAEJUAgAAAERGFAQAAEZIDgAAAEhSBgQCBkpMFAIAAExODgIAAE5SBgQCBFBEAgAAAFBKAgAAAFJY", "AgAAAFRQAgAAAFRWAgAAAFYGAgAAAFhUAgAAAFpcChAAAFxqChIAAF5qChIAAGBiCgIAAGJkBggEAGRm", "CgYAAGZqAgAAAGhaAgAAAGheAgAAAGhgAgAAAGoKAgAAAG4gAgAAAG4wAgAAAHJuBgQCAAwkQFBUaG4M", - "CggCRPYBAAAMBAIAAAoAAAAAAAAAAAAGAQAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "CggCRPYBAAAMBAIAAAoAAAAAAAAAAAAGAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAGDY2NjZUZmZ4igGKAZwBogG0AcYB5AHkAeQB5AH2AfYB9gH2AfYB9gH2AfYB", "9gH2AfYB9gH2AfYB9gECAgIICAQSEgYUFAgCAgoICAwQEA4SEhAUFBICAhQICBYQEBgSEhoUFBwCAh4I", "CCASFBIEBCIGBiQIDiYEBCIGBigIDiYCAioICCASFBwSEiwEBC4GBjAIDjIEBC4GBjQIDjICAjYICCAQ", - "EDgSEjoUFDwCAj4ICEASFEIcFAYGCAogBAYIKgQGCCwGBggKLgQGCDIEBgg0BAYINgQGCDgEBgg6BAYI", - "PAQGCD4EBghABAYIQgQGCAQGEgAEAgAAAAASEhIICAIKDAQODgIAAQoYAAQEBAIEAAAAAAAYGBgYGAEB", - "AgQEBAYGBggOCAABDCQABAQEBAIEAAAAAAAAJCQkJCQkAQECBAQEBgYGCAgICgwKDg4IAAECAAQAAAAA", - "AgYEAgQEBgg=" + "EDgSEjoUFDwCAj4ICEASFEIgFAYGCAogBAYIJAQICioEBggsBgYICi4EBggwBgYICjIEBgg0BAYINgQG", + "CDgEBgg6BAYIPAQGCD4EBghABAYIQgQGCAQGEgAEAgAAAAASEhIICAIKDAQODgIAAQoYAAQEBAIEAAAA", + "AAAYGBgYGAEBAgQEBAYGBggOCAABDCQABAQEBAIEAAAAAAAAJCQkJCQkAQECBAQEBgYGCAgICgwKDg4I", + "AAECAAQAAAAAAgYEAgQEBgg=" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index 820d6a399a..1325e4d194 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -1080,11 +1080,11 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn name(&mut self,) -> Result<&'arena NameContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - if let Some(_node) = recog.base.resume_take(RULE_name) { + if let Some(_node) = self.base.resume_take(RULE_name)? { return Ok(_node.as_rule_context().unwrap()); } + dbt_antlr4::maybe_grow_stack!({ + let recog = self; let _parentctx = recog.base.take_ctx(); recog.base.enter_rule(NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_name)?; let _local_ctx_fn = |recog: &Self| -> &'arena NameContext {recog.ctx().unwrap().as_rule_context().unwrap()}; diff --git a/runtime/Rust/tests/paren_differential_tests.rs b/runtime/Rust/tests/paren_differential_tests.rs index 5d81036b34..f530d69133 100644 --- a/runtime/Rust/tests/paren_differential_tests.rs +++ b/runtime/Rust/tests/paren_differential_tests.rs @@ -117,4 +117,3 @@ fn paren_family_corners_agree() { check(corner); } } - diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index be1ac64aec..8f969a7b55 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -538,9 +538,9 @@ where Input: TokenStream\<'input, 'arena, TF> + 'arena, { }>pub fn (&mut self,) -> Result\<&'arena All\<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ let recog = self; - let _parentctx = .base.take_ctx(); .base.enter_rule(Ext::create(.get_arena(), _parentctx, .get_state()}>)?, , RULE_)?; let _local_ctx_fn = |recog: &Self| -> &'arena \ {recog.ctx().unwrap().as_rule_context().unwrap()}; @@ -583,17 +583,13 @@ where { #[inline] }>pub fn (&mut self,) -> Result\<&'arena All\<'input, 'arena, TF::Tok\>, ANTLRError> { - { - let recog = &mut *self; - - } self._rec(0}>) } fn _rec(&mut self, _p: i32}>) -> Result\<&'arena All\<'input, 'arena, TF::Tok\>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ let recog = self; - let _parentctx = .base.take_ctx(); let _parentState = .base.get_state(); .base.enter_recursion_rule(Ext::create(.get_arena(), _parentctx, .get_state()}>)?, , RULE_, _p)?; @@ -858,37 +854,45 @@ descentMaskPredict(choice, groups) ::= << DescentGroup(g, tails) ::= << x if x != 0 && (x & !) == 0 && (x & (x-1)) != 0 && !.base.resume_active() => { - let _pos0 = .input.index(); -.base.match_token(,&mut .err_handler)?; -}> .base.set_state(); - .base.begin_mute(); - let _errs = .base.syntax_error_count(); + let _neutral_state = .base.begin_neutral_parse(); match .() { - Err(e) if !e.is_recoverable() => return Err(e), + Err(e) if !e.is_recoverable() => { + .base.end_neutral_parse(&_neutral_state); + return Err(e) + }, Err(_) => { - .base.end_mute(); - .input.seek(_pos0); + .base.end_neutral_parse(&_neutral_state); 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) }, Ok(_node) => { - .base.end_mute(); - if .base.syntax_error_count() != _errs { + if .base.syntax_error_count() != _neutral_state.2 { + .base.end_neutral_parse(&_neutral_state); // errorful neutral parse: throw its result away and // defer (muted, so no spurious reports escaped) - .base.discard_graft(dbt_antlr4::tree::NodeInner::as_node(_node), ); - .input.seek(_pos0); 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) } else { - // the tail token decides on the post-prefix stream; - // only then rewind into resume mode + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything let _tailbit = match .input.la(1) { - - _ => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) + + _ => Some()None, }; - .base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_, _pos0, ); - _tailbit + match _tailbit { + Some(bit) => { + .base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_); + .base.end_neutral_parse(&_neutral_state); + bit + } + None => { + .base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) + } + } } }, } @@ -896,14 +900,14 @@ DescentGroup(g, tails) ::= << x if x != 0 && (x & !) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), >> -Tail(t) ::= " => ," +Tail(t) ::= " => Some()," // Resume-mode short-circuit at the top of a resume-target rule: when a // shared-descent re-descent reaches the common rule, return the stored // prefix context (grafted under the caller, stream restored to the // tail by resume_take) instead of parsing it again. resumeTakeHook(currentRule) ::= << -if let Some(_node) = recog.base.resume_take(RULE_) { +if let Some(_node) = self.base.resume_take(RULE_)? { return Ok(_node.as_rule_context().unwrap()); } >> diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 4a1076cf53..ac85268f19 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -508,7 +508,20 @@ public Result(DecisionState decisionState) { protected boolean allStartViaR(Set configs, DecisionState s, SharedDescentAnalyzer.Group grp) { for (ATNConfig c : configs) { - if (grp.alts.get(c.alt) && !descentAnalyzer().startsViaR(c, s, grp)) return false; + if (!grp.alts.get(c.alt)) continue; + // boundary-popped configurations carry no first-consumer + // evidence (their chain is the wildcard context), but the + // inputs that produced them reached this state through R's + // span, so the neutral R call succeeds for them too + if (c.context == null || c.context.isEmpty()) continue; + if (!descentAnalyzer().startsViaR(c, s, grp)) { + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("STARTSVIA-FAIL d=%d alt=%d state=%d taint=%d ctx=%s%n", + s.decision, c.alt, c.state.stateNumber, c.reachesIntoOuterContext, + decodeContext(c.context)); + } + return false; + } } return true; } @@ -1184,6 +1197,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { // generated parser executes the group's shared prefix and // defers the choice to its tail decision PrefixFactorAnalyzer.Group factorGroup = currentFactorPlan != null + && System.getProperty("antlr.dfa.disableFactorMasks") == null ? currentFactorPlan.groupCovering(alts) : null; if (factorGroup != null) res.factorMaskStates++; if (PredictionMode.hasSLLConflictTerminatingPrediction(PredictionMode.SLL, cs)) { @@ -1419,12 +1433,16 @@ else if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { // resolves the choice at the tail decision) if (factorGroup != null) { res.factorEscapesCured++; + res.approxConflicts.remove(conflicting); + res.contextSensitiveConflicts.remove(conflicting); + res.exactAmbigConflicts.add(conflicting); acceptMasks.set(d, altBits(factorGroup.alts)); } else { SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null + && System.getProperty("antlr.dfa.disableDescentMasks") == null ? currentDescentPlan.groupCovering(alts) : null; - if (descentGroup != null && allStartViaR(configs, s, descentGroup)) { + if (descentGroup != null) { res.descentMaskStates++; res.approxConflicts.remove(conflicting); res.contextSensitiveConflicts.remove(conflicting); @@ -1483,8 +1501,9 @@ else if (abortOnUntrustedConflict) { } else { SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null + && System.getProperty("antlr.dfa.disableDescentMasks") == null ? currentDescentPlan.groupCovering(alts) : null; - if (descentGroup != null && allStartViaR(configs, s, descentGroup)) { + if (descentGroup != null) { res.descentMaskStates++; acceptMasks.set(d, altBits(alts)); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { diff --git a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java index 8a7f6e0c83..2862921da4 100644 --- a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java +++ b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java @@ -86,9 +86,11 @@ public Group(int rule, BitSet alts) { * pure zero-token descent). */ public final List prefixTokens = new ArrayList(); /** The block's full mask: member alternatives plus prefix-sharing - * non-members (they fall through to the widen arm, which defers - * to adaptivePredict - so their conflicts never need resolving, - * but their states are accepted). */ + * non-members admitted by {@link #widenHarmless} (their spans + * can never coincide with a member's neutral-R span, so when + * the neutral parse succeeds the tail dispatch cannot overrule + * adaptivePredict's min-alt resolution, and when it fails the + * block falls back to the adaptive engine). */ public final BitSet blockAlts = new BitSet(); /** The R-call follow states of the member alternatives: the * prefix-side boundary of the first-consumer proof (frames @@ -142,6 +144,13 @@ public Plan buildPlan(DecisionState s) { } for (int a = 1; a <= s.getNumberOfTransitions(); a++) { for (AltPath p : altPaths(s, a)) { + if (!firstConsumerUnique(s, a, p)) { + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("CAND-REJ d=%d alt=%d rule=%s prefix=%s%n", s.decision, a, + g.getRule(p.rule).name, p.tokens); + } + continue; + } String key = p.rule + "|" + p.tokens; byKey.computeIfAbsent(key, k -> new BitSet()).set(a); pathsByKey.computeIfAbsent(key, k -> new ArrayList()).add(p); @@ -158,18 +167,16 @@ public Plan buildPlan(DecisionState s) { grp.boundaryStates.add(p.boundary); } analyzeDispatch(s, grp); - boolean dj = disjointOk(s, grp); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { - System.err.printf("DISPATCH d=%d rule=%s alts=%s default=%d arms=%s disjoint=%s%n", - s.decision, g.getRule(grp.rule).name, grp.alts, grp.defaultAlt, grp.explicitArms, dj); + System.err.printf("DISPATCH d=%d rule=%s alts=%s default=%d arms=%s%n", + s.decision, g.getRule(grp.rule).name, grp.alts, grp.defaultAlt, grp.explicitArms); } - if (grp.codegenable && !dj) grp.codegenable = false; - // the block's mask widens to prefix-sharing non-members (they - // fall through to the widen arm, so their states are accepted - // without any conflict resolution of their own) + // the block's mask widens to prefix-sharing non-members whose + // own spans cannot be confused with a member's (their states + // then need no conflict resolution of their own) if (grp.codegenable && !grp.prefixTokens.isEmpty()) { for (int a = 1; a <= s.getNumberOfTransitions(); a++) { - if (!grp.alts.get(a) && postPrefixState(s, a, grp.prefixTokens) != null) { + if (!grp.alts.get(a) && widenHarmless(s, grp, a)) { grp.blockAlts.set(a); } } @@ -185,36 +192,41 @@ public Plan buildPlan(DecisionState s) { } /** - * The ambiguity disjointness check for an expression-first - * dispatch: some non-member alternative sharing the prefix could - * also complete with the same tail. That happens exactly when a - * single token completes both the non-member alternative and R - * itself (e.g. {@code (TABLE)} as a parenthesized expression vs as - * a query): then a clean R parse with that tail is not unique to - * the member and the group must be deferred. The check is precise: - * for every content-first token of every prefix-sharing non-member - * alternative, require that it cannot complete BOTH that - * alternative and R. + * May the block's mask safely cover states where the prefix-sharing + * non-member alternative {@code a} is live? The neutral R parse + * plus tail dispatch commits to a member alternative, so a live + * non-member is dangerous exactly when the input can complete BOTH + * a member (span = prefix + an R string) and {@code a} itself AND + * adaptivePredict's min-alt resolution would prefer {@code a} over + * the member the dispatch commits to (e.g. {@code ( query )} next + * to a {@code ( expression )} group: {@code (SELECT 1)} is both a + * parenthesized expression over a subquery and a direct subquery, + * and the direct subquery alternative wins). Two conservative + * sufficient conditions for harmlessness: every member is + * lower-numbered than {@code a} (the min-alt rule then always + * prefers a member, whichever one the dispatch commits to), or no + * string can be both an R derivation and {@code a}'s post-prefix + * content - over-approximated by disjoint FIRST sets (this also + * covers the {@code (TABLE)}-style exact-single-token collision, + * which is a special case of FIRST overlap). Otherwise the + * alternative is left out of the mask and its states fall back to + * the adaptive engine. */ - private boolean disjointOk(DecisionState s, Group grp) { + private boolean widenHarmless(DecisionState s, Group grp, int a) { + ATNState post = postPrefixState(s, a, grp.prefixTokens); + if (post == null) return false; // does not share the prefix: irrelevant + if (a >= grp.alts.length()) return true; // every member beats a on min-alt + if (System.getProperty("antlr.dfa.disableWidenGate") != null) return true; LL1Analyzer ll1 = new LL1Analyzer(atn); - for (int a = 1; a <= s.getNumberOfTransitions(); a++) { - if (grp.alts.get(a)) continue; - ATNState post = postPrefixState(s, a, grp.prefixTokens); - if (post == null) continue; // does not share the prefix: irrelevant - for (int t : ll1.LOOK(post, null).toArray()) { - if (t <= 0) continue; - boolean cr = canBeExactly(atn.ruleToStartState[grp.rule], t); - boolean ca = canBeExactly(post, t); - // a genuine collision is fatal only when the runtime's - // min-alt resolution would prefer the non-member over - // every member of the group - if (cr && ca && a < grp.alts.nextSetBit(0)) { - if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { - System.err.printf("DISJOINT-FAIL d=%d alt=%d token=%d%n", s.decision, a, t); - } - return false; + IntervalSet look = ll1.LOOK(post, null); + IntervalSet firstR = ll1.LOOK(atn.ruleToStartState[grp.rule], null); + for (int t : look.toArray()) { + if (t > 0 && firstR.contains(t)) { + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("WIDEN-VETO d=%d alt=%d rule=%s first=%d%n", + s.decision, a, g.getRule(grp.rule).name, t); } + return false; } } return true; @@ -252,45 +264,6 @@ else if (t.label() != null && t.label().contains(want)) { return null; } - /** Can the language from {@code start} be exactly token {@code t} - * (consume {@code t}, then reach a rule stop with only epsilon - * steps)? */ - private boolean canBeExactly(ATNState start, int t) { - Set seen = new HashSet(); - Deque work = new ArrayDeque(); - work.add(new Object[]{start, Boolean.FALSE}); - while (!work.isEmpty()) { - Object[] item = work.poll(); - ATNState st = (ATNState)item[0]; - boolean consumed = (Boolean)item[1]; - String key = st.stateNumber + ":" + consumed; - if (!seen.add(key)) continue; - if (st instanceof RuleStopState) { - if (consumed) return true; - continue; - } - for (int i = 0; i < st.getNumberOfTransitions(); i++) { - Transition tr = st.transition(i); - if (tr instanceof RuleTransition) { - // descending into a callee stays epsilon only when its - // interior is token-free: in the consumed phase its - // token transitions are pruned below, leaving only the - // nullable paths - work.add(new Object[]{tr.target, consumed}); - work.add(new Object[]{((RuleTransition)tr).followState, consumed}); - } - else if (tr.isEpsilon()) { - work.add(new Object[]{tr.target, consumed}); - } - else if (!consumed && tr.label() != null && tr.label().contains(t)) { - work.add(new Object[]{tr.target, Boolean.TRUE}); - } - // any other token consumption breaks exactness - } - } - return false; - } - /** * Does the decision's emitted table contain a mask-accept covered * by one of the plan's descent groups (any multi-alt subset of a @@ -306,9 +279,9 @@ public static boolean hasDescentMask(Grammar g, int decision) { for (long m : dfa.acceptMasks) { if (m == 0 || (m & (m-1)) == 0) continue; // singletons take ordinary arms for (Group grp : plan.groups) { - if (!grp.codegenable) continue; - BitSet cover = grp.blockAlts.isEmpty() ? grp.alts : grp.blockAlts; - long bits = 0; + if (!grp.codegenable) continue; + BitSet cover = grp.blockAlts.isEmpty() ? grp.alts : grp.blockAlts; + long bits = 0; for (int a = cover.nextSetBit(0); a >= 0; a = cover.nextSetBit(a+1)) bits |= 1L << (a-1); if ((m & ~bits) == 0) return true; } @@ -530,6 +503,9 @@ && allCallSitesToBoundary(ctx.getParent(i), callSites, boundary, visited)) { * prefix is empty) to the group's rule. */ private Set epsilonCallSites(DecisionState s, Group grp) { String key = s.decision + ":" + grp.rule + ":" + grp.prefixTokens.hashCode(); + if ("descent".equals(System.getProperty("antlr.dfa.debug")) && !callSitesCache.containsKey(key)) { + System.err.printf("CALLSITES-G d=%d rule=%s%n", s.decision, g.getRule(grp.rule).name); + } Set sites = callSitesCache.get(key); if (sites == null) { sites = new HashSet(); @@ -553,6 +529,9 @@ private Set epsilonCallSites(DecisionState s, Group grp) { if (t instanceof RuleTransition) { RuleTransition rt = (RuleTransition)t; sites.add(rt.followState.stateNumber); + // the descent continues after the call too: chains + // like identifier -> over -> identifier pass through + work.add(rt.followState); if (rt.target.ruleIndex != grp.rule) work.add(t.target); } else if (t.isEpsilon()) { @@ -561,6 +540,10 @@ else if (t.isEpsilon()) { } } callSitesCache.put(key, sites); + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("CALLSITES-GS d=%d rule=%s sites=%s%n", s.decision, + g.getRule(grp.rule).name, sites); + } } return sites; } @@ -586,6 +569,7 @@ private Set epsilonCallSites(DecisionState s, int ruleR) { if (t instanceof RuleTransition) { RuleTransition rt = (RuleTransition)t; sites.add(rt.followState.stateNumber); + work.add(rt.followState); if (rt.target.ruleIndex != ruleR) work.add(t.target); } else if (t.isEpsilon()) { @@ -728,6 +712,45 @@ else if (!inRule && t.label() != null && tokens.size() < MAX_PREFIX_TOKENS) { return out; } + /** Is R the unique first consuming position of alternative + * {@code alt} after its prefix? The neutral parse invokes R + * immediately after the prefix, so a member alternative's body + * must not be able to consume anything - a token or a non-R call + * - before its first R call, nor to reach the end of the decision + * rule before it. Otherwise the neutral R span and the body's + * first R call can cover different tokens (e.g. {@code TRIM LPAREN + * (trimsSpecification? valueExpression? FROM) ...}, where BOTH is + * a trimsSpecification to the body but identifier content to the + * neutral R) and the resume graft would attach at the wrong + * place. */ + private boolean firstConsumerUnique(DecisionState s, int alt, AltPath p) { + ATNState start = postPrefixState(s, alt, p.tokens); + if (start == null) return false; + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + work.add(start); + boolean any = false; + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st)) continue; + if (st instanceof RuleStopState) return false; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + if (((RuleTransition)t).target.ruleIndex != p.rule) return false; + any = true; + } + else if (t.isEpsilon()) { + work.add(t.target); + } + else { + return false; + } + } + } + return any; + } + /** Can R be reached from {@code start} following epsilon * transitions and rule calls only (zero tokens)? */ private boolean descendsToR(ATNState start, int ruleR, Set seen) { From 6b98f6a4ed9a223986085f0939681f4563eb0693 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 25 Jul 2026 01:47:59 -0400 Subject: [PATCH 27/48] Bump version to 2.0.1 Patch bump across all lockstep version locations: - Maven parent + 5 modules (runtime/Java, tool, antlr4-maven-plugin, tool-testsuite, runtime-testsuite) - Rust crate (Cargo.toml + Cargo.lock) - runtime/Rust/gen_test_grammars.sh TOOL_VERSION Signed-off-by: Bo Lin --- antlr4-maven-plugin/pom.xml | 2 +- pom.xml | 2 +- runtime-testsuite/pom.xml | 2 +- runtime/Java/pom.xml | 2 +- runtime/Rust/Cargo.lock | 2 +- runtime/Rust/Cargo.toml | 2 +- runtime/Rust/gen_test_grammars.sh | 2 +- tool-testsuite/pom.xml | 2 +- tool/pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/antlr4-maven-plugin/pom.xml b/antlr4-maven-plugin/pom.xml index 492367b950..a40dbb9adf 100644 --- a/antlr4-maven-plugin/pom.xml +++ b/antlr4-maven-plugin/pom.xml @@ -8,7 +8,7 @@ org.antlr antlr4-master - 2.0.0 + 2.0.1 antlr4-maven-plugin maven-plugin diff --git a/pom.xml b/pom.xml index 161a5ad485..b913d9a98d 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ org.antlr antlr4-master - 2.0.0 + 2.0.1 pom ANTLR 4 diff --git a/runtime-testsuite/pom.xml b/runtime-testsuite/pom.xml index e324b0de7a..93af0df9e3 100644 --- a/runtime-testsuite/pom.xml +++ b/runtime-testsuite/pom.xml @@ -10,7 +10,7 @@ org.antlr antlr4-master - 2.0.0 + 2.0.1 antlr4-runtime-testsuite ANTLR 4 Runtime Tests (4th generation) diff --git a/runtime/Java/pom.xml b/runtime/Java/pom.xml index f16ceff18c..f0e673add4 100644 --- a/runtime/Java/pom.xml +++ b/runtime/Java/pom.xml @@ -9,7 +9,7 @@ org.antlr antlr4-master - 2.0.0 + 2.0.1 ../../pom.xml antlr4-runtime diff --git a/runtime/Rust/Cargo.lock b/runtime/Rust/Cargo.lock index dbc1f787ee..8b34e291c8 100644 --- a/runtime/Rust/Cargo.lock +++ b/runtime/Rust/Cargo.lock @@ -71,7 +71,7 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "dbt-antlr4" -version = "2.0.0" +version = "2.0.1" dependencies = [ "bit-set", "bumpalo", diff --git a/runtime/Rust/Cargo.toml b/runtime/Rust/Cargo.toml index a2bb3c91b3..8787a63e5d 100644 --- a/runtime/Rust/Cargo.toml +++ b/runtime/Rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dbt-antlr4" -version = "2.0.0" +version = "2.0.1" authors = ["Konstantin Anisimov ", "Alex Snaps ", "Bo Lin "] homepage = "https://github.com/sdf-labs/antlr4" repository = "https://github.com/sdf-labs/antlr4" diff --git a/runtime/Rust/gen_test_grammars.sh b/runtime/Rust/gen_test_grammars.sh index 7a9c335afe..4e3f1dfa1e 100755 --- a/runtime/Rust/gen_test_grammars.sh +++ b/runtime/Rust/gen_test_grammars.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -TOOL_VERSION="2.0.0" +TOOL_VERSION="2.0.1" ANTLR_PATH="../../../tool/target/dbt-antlr4-${TOOL_VERSION}-complete.jar" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" diff --git a/tool-testsuite/pom.xml b/tool-testsuite/pom.xml index bc0c297f95..ec887bc17b 100644 --- a/tool-testsuite/pom.xml +++ b/tool-testsuite/pom.xml @@ -10,7 +10,7 @@ org.antlr antlr4-master - 2.0.0 + 2.0.1 antlr4-tool-testsuite ANTLR 4 Tool Tests diff --git a/tool/pom.xml b/tool/pom.xml index a9c6372b28..bb2d8cdf2e 100644 --- a/tool/pom.xml +++ b/tool/pom.xml @@ -9,7 +9,7 @@ org.antlr antlr4-master - 2.0.0 + 2.0.1 antlr4 ANTLR 4 Tool From 7d26192913565e37d7cfc88673f6c7173f729bb6 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 25 Jul 2026 09:18:16 -0400 Subject: [PATCH 28/48] DecisionClassifier: cut static-DFA analysis time (constant-factor + right-sized overflow cap) Static-DFA table construction was dominated by DecisionClassifier.closure; profiling attributed ~91% of -Xstatic-dfa build time to it, driven by raw closure count (Trino 40M, Databricks 473M) concentrated in a few dozen hard decisions per grammar. Four fixes, none of which change results: - maxDfaStates 2000 -> 1000 (now -Dantlr.dfa.maxDfaStates=N tunable). The cap is an overflow trigger, not a coverage target: decisions needing unbounded lookahead expand to the full cap before being abandoned to a hybrid/adaptive fallback, so the cap is a direct linear factor on worst-case time (and precedence rules pay it per precedence class). The largest table any decision actually resolves to across the SQL dialect grammars is ~700 states, so 1000 leaves headroom while halving the doomed frontier. Lowering the cap is sound by construction - it only shifts hard decisions to adaptivePredict, never mis-predicts - and emits an identical set of static prediction sites on every tested grammar (zero coverage loss). - hasReturnState: iterative singleton fast-path. It ran once per rule transition per closure step and allocated a fresh IdentityHashMap each call for an O(depth) DAG walk; contexts are overwhelmingly cycle-free singleton chains, so walk parent pointers directly and fall back to the visited-set DAG walk only when a merged (array) node appears. - ConfigSetKey: cache the config-set hash used to key the DFA-state dedup map and the successor-merge map. A raw Set key recomputed AbstractSet.hashCode - O(|set|), summing every member's hash - on every get/put; caching collapses that to once per set (equality unchanged). - Presize the per-class/per-start closure busy sets to cut HashMap resizes (previously the top self-time frame). Static gen wall time: Trino 5.0->3.8s, Databricks 38.7->26.6s, Duckdb 25.1->18.0s, Snowflake 27.3->21.1s. Differential (static vs adaptive) unchanged (2 known :: error-path divergences), tests/gen byte-identical, cargo 11/11, tool-testsuite 694/0, runtime-testsuite rust.** 707/707. Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 84 +++++++++++++++---- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index ac85268f19..b5dc951b8e 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -281,8 +281,24 @@ public Result(DecisionState decisionState) { /** Taint bits that make any conflict untrusted outright. */ protected static final int HARD_TAINT = WIDENED_TAINT | PRECPRED_TAINT; - /** Hard cap on DFA states per decision (per construction attempt). */ - public int maxDfaStates = 2000; + /** + * Hard cap on DFA states per decision (per construction attempt). + * + *

This is an overflow trigger, not a coverage target: any decision + * that needs more than this many states is abandoned to a hybrid table + * or {@code adaptivePredict} (always sound - a smaller cap only shifts + * work to the adaptive engine, it can never mis-predict). It exists to + * bound the cost of the doomed exact-context attempt on decisions that + * require unbounded lookahead: that attempt expands to exactly this + * many states before overflowing, so the cap is a direct linear factor + * on the analyzer's worst-case time. Across the SQL dialect grammars + * the largest table any decision actually resolves to is ~700 states, + * so the default leaves comfortable headroom while keeping the doomed + * frontier ~2x smaller than the historical 2000. Override with + * {@code -Dantlr.dfa.maxDfaStates=N} for grammars with unusually deep + * decisions.

+ */ + public int maxDfaStates = Integer.parseInt(System.getProperty("antlr.dfa.maxDfaStates", "1000")); /** * Hybrid-table construction bounds (see {@link Category#HYBRID}): the @@ -1134,7 +1150,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { this.faithCache = new java.util.IdentityHashMap(); this.widenedJoints = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()); - Map, Integer> stateIds = new HashMap, Integer>(); + Map stateIds = new HashMap(); List> states = new ArrayList>(); List> edges = new ArrayList>(); List> edgeLabels = new ArrayList>(); @@ -1144,7 +1160,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List stateDepth = new ArrayList(); // lookahead depth (BFS layer) Set start = new LinkedHashSet(); - Set startBusy = new HashSet(); + Set startBusy = new HashSet(1024); this.precStartClosure = precRuleIndex >= 0; for (int i = 0; i < s.getNumberOfTransitions(); i++) { closure(new ATNConfig(s.transition(i).target, i+1, EmptyPredictionContext.Instance), @@ -1164,7 +1180,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { c.reachesIntoOuterContext, c.isPrecedenceFilterSuppressed(), c.context); } } - stateIds.put(start, 0); + stateIds.put(new ConfigSetKey(start), 0); states.add(start); edges.add(new ArrayList()); edgeLabels.add(new ArrayList()); @@ -1536,11 +1552,12 @@ else if (abortOnUntrustedConflict) { fallbackAlts.set(d, fallback); for (LabeledSuccessor ls : successors(configs, res)) { - Integer id = stateIds.get(ls.configs); + ConfigSetKey lsKey = new ConfigSetKey(ls.configs); + Integer id = stateIds.get(lsKey); if (id == null) { if (states.size() >= maxDfaStates) { overflow = true; break; } id = states.size(); - stateIds.put(ls.configs, id); + stateIds.put(lsKey, id); states.add(ls.configs); edges.add(new ArrayList()); edgeLabels.add(new ArrayList()); @@ -1758,6 +1775,29 @@ protected static final class LabeledSuccessor { } } + /** + * Map key wrapping a configuration set with its hash computed once. + * The DFA-state dedup map ({@code stateIds}) and the per-state + * successor-merge map ({@code bySuccessor}) are keyed by config sets; + * a raw {@code Set} key recomputes {@link java.util.AbstractSet#hashCode} + * - O(|set|), summing every member's hash - on every get/put. Caching + * it collapses those repeated scans to one per set while preserving + * set equality (equals still falls back to {@code Set.equals}, but only + * on a hash collision). + */ + protected static final class ConfigSetKey { + final Set set; + final int hash; + ConfigSetKey(Set set) { this.set = set; this.hash = set.hashCode(); } + @Override public int hashCode() { return hash; } + @Override public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ConfigSetKey)) return false; + ConfigSetKey k = (ConfigSetKey)o; + return hash == k.hash && set.equals(k.set); + } + } + /** * Compute the successor configuration sets of a DFA state, one edge per * distinct successor set, labeled with the full token class (never per @@ -1833,11 +1873,11 @@ else if (t instanceof WildcardTransition) { } // close each class; merge classes that reach the same successor set - Map, IntervalSet> bySuccessor = new LinkedHashMap, IntervalSet>(); + Map bySuccessor = new LinkedHashMap(); for (Map.Entry e : classLabels.entrySet()) { BitSet key = e.getKey(); Set succ = new LinkedHashSet(); - Set busy = new HashSet(); + Set busy = new HashSet(1024); for (int m = key.nextSetBit(0); m >= 0; m = key.nextSetBit(m+1)) { ATNConfig c = moveConfigs.get(m); if (moveIsStop.get(m)) { @@ -1871,9 +1911,10 @@ else if (t instanceof WildcardTransition) { } } succ = canonical(succ); - IntervalSet merged = bySuccessor.get(succ); + ConfigSetKey succKey = new ConfigSetKey(succ); + IntervalSet merged = bySuccessor.get(succKey); if (merged == null) { - bySuccessor.put(succ, e.getValue()); + bySuccessor.put(succKey, e.getValue()); } else { merged.addAll(e.getValue()); @@ -1881,8 +1922,8 @@ else if (t instanceof WildcardTransition) { } List result = new ArrayList(bySuccessor.size()); - for (Map.Entry, IntervalSet> e : bySuccessor.entrySet()) { - result.add(new LabeledSuccessor(e.getValue(), e.getKey())); + for (Map.Entry e : bySuccessor.entrySet()) { + result.add(new LabeledSuccessor(e.getValue(), e.getKey().set)); } return result; } @@ -2404,8 +2445,21 @@ protected boolean runtimeFaithful(ATNConfig c) { protected Map faithCache; protected static boolean hasReturnState(PredictionContext ctx, int returnStateNumber) { - return hasReturnState(ctx, returnStateNumber, - java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); + // Fast path: singleton chains (the overwhelmingly common context + // shape) are cycle-free linked lists, so they need no visited set - + // walking parent pointers avoids allocating an IdentityHashMap on + // every call (this runs once per rule transition per closure step). + // Fall back to the DAG walk only when a merged (array) node appears. + while (ctx != null && !ctx.isEmpty()) { + if (ctx.size() != 1) { + return hasReturnState(ctx, returnStateNumber, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); + } + if (ctx.getReturnState(0) == returnStateNumber) return true; + if (ctx.getReturnState(0) == PredictionContext.EMPTY_RETURN_STATE) return false; + ctx = ctx.getParent(0); + } + return false; } private static boolean hasReturnState(PredictionContext ctx, int returnStateNumber, Set visited) { From d9d7a4aa44e3a84704078f6142b571d2f2499f1e Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 25 Jul 2026 09:55:24 -0400 Subject: [PATCH 29/48] DecisionClassifier: skip doomed exact-attempt expansion in -Xdecision-report (lossless two-pass) The decision report (-Xdecision-report) ran classifyAll with no early termination, so every decision with unbounded lookahead expanded its exact-context attempt to the full state cap before overflowing - work that classify() then discards, since the reported Result for such a decision comes from the subsequent bound-0 / hybrid attempt, not the doomed exact one. That made the report many times slower than table building and dominated its wall time (Trino ~86s, Redshift ~330s). Add abortInfAsOverflow: in a non-hybrid attempt, treat the first untrusted conflict as a state overflow (overflow=true; break) rather than exploring to completion. Unlike the table builder's abortOnUntrustedConflict (which returns CONTEXT_SENSITIVE and skips the remaining widening depths), this keeps classify()'s full widening-then-hybrid flow intact. This is exactly transparent for any decision that resolves to a static or hybrid table: clean tables never hit an untrusted conflict (so are never short-circuited), and whether a decision gets a hybrid table - and its escape-state detail - is decided by the hybrid pass, which is never short-circuited (the flag is gated out under hybridMode). It is NOT transparent for a decision that ends on the adaptive engine: there the report would display the short-circuited attempt's category/conflict inventory instead of the true full-exploration one - and those are precisely the "remaining adaptive fallback" decisions the report exists to explain. So report() runs two passes: the fast pass with the flag, then a re-classification of exactly the adaptive-fallback decisions (non-precedence with no table; precedence with an adaptive class) without the flag, restoring their exact category and complete conflict inventory. That set is empty on well-covered grammars (the report stays fast) and small otherwise (a grammar with many is barely statically covered). Report output is byte-identical to the full no-abort report on all six SQL dialect grammars, and - stress-tested at maxDfaStates=60, which forces 58 fully-adaptive Trino decisions through the re-run path - byte-identical there too. Table building is untouched (it never sets the flag), so emitted tables are unchanged. Wall time: Trino 210s->5s, Redshift 330s->17s (the 210->86s part came from the prior maxDfaStates commit). tests/gen byte-identical, static prediction sites unchanged, cargo 11/11, tool-testsuite 694/0, runtime-testsuite rust.** 707/707. Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index b5dc951b8e..d756f76033 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -349,6 +349,23 @@ public Result(DecisionState decisionState) { */ public boolean abortOnUntrustedConflict = false; + /** + * When set (report mode, first pass), treat an untrusted conflict in a + * non-hybrid attempt as a state overflow instead of exploring the + * doomed attempt to completion. Unlike {@link #abortOnUntrustedConflict} + * (table mode), this preserves classify()'s full widening-then-hybrid + * flow. For any decision that resolves to a static or hybrid table the + * resulting {@link Result} is therefore identical to a full exploration + * (clean tables never hit an untrusted conflict, so are never + * short-circuited; hybrid detail comes from the untouched hybrid pass), + * while the deep doomed closure that dominates report time is skipped. + * A decision that instead ends on the adaptive engine may get a + * different category/conflict inventory under this flag; {@link #report} + * re-classifies exactly those without it. Left false for table building + * (which must not perturb which tables it emits). + */ + public boolean abortInfAsOverflow = false; + protected final Grammar g; protected final ATN atn; protected final IntervalSet allTokens; @@ -1497,6 +1514,26 @@ else if (abortOnUntrustedConflict) { res.category = Category.CONTEXT_SENSITIVE; return false; } + else if (abortInfAsOverflow) { + // Report mode: an untrusted conflict means this exact + // (or context-free) attempt cannot yield a clean + // table, so its remaining expansion is discarded + // anyway - classify() proceeds to the next widening + // depth and then the hybrid attempt, which is what + // produces the reported result. Short-circuit the + // doomed expansion by declaring overflow here, taking + // exactly the same downstream path a real state + // overflow would. This is output-identical to the + // full exploration (a coarser bound-0 + // over-approximation carries at least the exact + // attempt's conflicts, so it can never resolve a + // table the exact attempt could not) but avoids the + // deep doomed closure that dominates -Xdecision-report + // time. Not used for table building, which keeps its + // own abort above. + overflow = true; + break; + } } continue; } @@ -2661,7 +2698,31 @@ private static void addSyntheticContinuationStates( /** Build the human-readable report printed by the -Xdecision-report tool option. */ public static String report(Grammar g) { DecisionClassifier classifier = new DecisionClassifier(g); + // First pass: short-circuit doomed exact/context-free attempts as + // overflow (see abortInfAsOverflow). This is transparent for every + // decision that resolves to a static or hybrid table - clean tables + classifier.abortInfAsOverflow = true; + // and hybrid results come from the untouched hybrid pass - but a + // decision that ends up on the adaptive engine (wholly, or a + // precedence class of it) would otherwise display the short-circuited + // attempt's category/conflicts instead of the full-exploration ones. + classifier.abortInfAsOverflow = true; List results = classifier.classifyAll(); + // Second pass: re-classify exactly those remaining adaptive-fallback + // decisions without the shortcut, restoring their true category and + // complete conflict inventory - the detail the report exists to + // provide. They are rare (a grammar with many is barely statically + // covered at all), so accuracy is restored at negligible cost; on + // well-covered grammars this set is empty and the report stays fast. + classifier.abortInfAsOverflow = false; + List decs = g.atn.decisionToState; + for (int i = 0; i < results.size(); i++) { + Result r = results.get(i); + boolean adaptiveFallback = r.category == Category.LR_PRECEDENCE + ? (r.precDfa == null || r.adaptiveClasses > 0) + : (r.category != Category.LL1 && r.dfa == null); + if (adaptiveFallback) results.set(i, classifier.classify(decs.get(i))); + } Map counts = new LinkedHashMap(); for (Category c : Category.values()) counts.put(c, 0); From 5df445b2734f58dd02378ec45f50f82b48b37ab8 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 25 Jul 2026 15:33:16 -0400 Subject: [PATCH 30/48] Rust static DFA: O(1) edge lookup via load-time row expansion The table-walk edge lookup was a binary search over the serialized (lo, hi, target) interval triples - O(log E) per token, with /3,*3 index math and multiple loads per probe. On 0-escape decisions that made the static walk ~1.5x slower per decision than the warm adaptive SLL DFA (which indexes its edge array in O(1)), so a long all-static parse lost to the adaptive engine it is meant to beat. Expand each table's edges into per-state direct-indexed rows at load time (from_int_stream), leaving the serialized blob unchanged (no code-size bloat, a memory-only expansion): edge_min[s] is the state's base token, edge_row_at is CSR offsets, edge_targets the flat rows (target per token in [min, min+len), -1 = no edge). edge() is now a bounds check plus one indexed load. Measured (Trino, Rust release, warm, SELECT A, A, ..., A FROM T, all 0-escape), same runtime with/without the change: cols static before -> after S/A before -> after 300 133.3us -> 97.2us 1.50 -> 1.10 Per-decision static cost 441ns -> 320ns (-27%), closing most of the gap to warm adaptive (289ns/decision). The residual 1.10x is the per-state metadata (accepts loaded twice + escape/mask/accept checks before the edge), a separate follow-up. Behavior unchanged: cargo 11/11, runtime-testsuite rust.** 707/707, parsebench static-vs-adaptive diff over corpus-pred 318/0 mismatches. Signed-off-by: Bo Lin --- runtime/Rust/src/static_dfa.rs | 109 +++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 25 deletions(-) diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs index 134c9643ab..f26837155a 100644 --- a/runtime/Rust/src/static_dfa.rs +++ b/runtime/Rust/src/static_dfa.rs @@ -79,6 +79,15 @@ pub struct StaticDFATables { dispatch_data: Vec, /// Per-dispatch start offset into `dispatch_data`. dispatch_at: Vec, + /// Per-table expanded edge lookup, built at load time from the compact + /// interval triples in `data` (memory-only; the serialized blob is + /// unchanged). `edge_min[t][s]` is state `s`'s base token, `edge_row_at[t]` + /// its CSR offsets (`num_states + 1`), and `edge_targets[t]` the flat + /// per-state rows: target state for each token in `[min, min+len)`, + /// `-1` where the state has no edge. Gives O(1) `edge()`. + edge_min: Vec>, + edge_row_at: Vec>, + edge_targets: Vec>, } /// Borrowed view of one decision's table. @@ -97,10 +106,14 @@ pub struct StaticDFATable<'a> { /// more precise error at the mismatch point - mirroring /// `adaptive_predict`'s finished-decision-entry-rule recovery. pub fallbacks: &'a [i32], - /// Index of each state's first edge `i32` in `edges`; `num_states + 1` entries. - pub edge_offsets: &'a [i32], - /// Flattened `(lo, hi, target)` triples, sorted by `lo` within each state. - pub edges: &'a [i32], + /// State `s`'s base token: `edge()` indexes `edge_targets` at + /// `edge_row_at[s] + (t - edge_min[s])`. + pub edge_min: &'a [i32], + /// CSR offsets into `edge_targets`, one per state plus a terminator. + pub edge_row_at: &'a [u32], + /// Flattened per-state direct-indexed edge rows: target state for each + /// token in the state's `[min, min+len)` range, `-1` where no edge. + pub edge_targets: &'a [i32], } impl StaticDFATables { @@ -115,6 +128,9 @@ impl StaticDFATables { decision_to_table: Vec::new(), dispatch_data: Vec::new(), dispatch_at: Vec::new(), + edge_min: Vec::new(), + edge_row_at: Vec::new(), + edge_targets: Vec::new(), } } @@ -141,6 +157,9 @@ impl StaticDFATables { let mut data = Vec::new(); let mut metas = Vec::with_capacity(num_tables); let mut masks = Vec::with_capacity(num_tables); + let mut edge_min: Vec> = Vec::with_capacity(num_tables); + let mut edge_row_at: Vec> = Vec::with_capacity(num_tables); + let mut edge_targets: Vec> = Vec::with_capacity(num_tables); let mut decision_to_table = vec![-1i32; num_slots]; for table in 0..num_tables { @@ -167,6 +186,42 @@ impl StaticDFATables { for _ in 0..num_edge_ints { data.push(next()); } + // Expand this table's compact interval triples into per-state + // direct-indexed rows for O(1) edge lookup at parse time. Kept + // out of the serialized blob (a memory-only expansion). + { + let eo = &data[edge_offsets_at..edges_at]; + let ed = &data[edges_at..edges_at + num_edge_ints]; + let mut t_min = vec![0i32; num_states]; + let mut t_row_at = vec![0u32; num_states + 1]; + let mut t_targets: Vec = Vec::new(); + for s in 0..num_states { + t_row_at[s] = t_targets.len() as u32; + let lo_tri = (eo[s] / 3) as usize; + let hi_tri = (eo[s + 1] / 3) as usize; + if lo_tri < hi_tri { + let mut smin = i32::MAX; + let mut smax = i32::MIN; + for tri in lo_tri..hi_tri { + smin = smin.min(ed[tri * 3]); + smax = smax.max(ed[tri * 3 + 1]); + } + t_min[s] = smin; + let base = t_targets.len(); + t_targets.resize(base + (smax - smin + 1) as usize, -1); + for tri in lo_tri..hi_tri { + let tgt = ed[tri * 3 + 2]; + for tok in ed[tri * 3]..=ed[tri * 3 + 1] { + t_targets[base + (tok - smin) as usize] = tgt; + } + } + } + } + t_row_at[num_states] = t_targets.len() as u32; + edge_min.push(t_min); + edge_row_at.push(t_row_at); + edge_targets.push(t_targets); + } // v6: alternative-mask section let num_mask_states = next() as usize; let mut table_masks = vec![0u64; num_states]; @@ -206,6 +261,9 @@ impl StaticDFATables { decision_to_table, dispatch_data, dispatch_at, + edge_min, + edge_row_at, + edge_targets, } } @@ -243,18 +301,14 @@ impl StaticDFATables { } } assert!(t >= 0, "no static DFA table for decision {}", decision); - let (accepts_at, fallbacks_at, edge_offsets_at, edges_at) = self.metas[t as usize]; - let end = self - .metas - .get(t as usize + 1) - .map(|m| m.0) - .unwrap_or(self.data.len()); + let (accepts_at, fallbacks_at, edge_offsets_at, _edges_at) = self.metas[t as usize]; Some(StaticDFATable { accepts: &self.data[accepts_at..fallbacks_at], masks: &self.masks[t as usize], fallbacks: &self.data[fallbacks_at..edge_offsets_at], - edge_offsets: &self.data[edge_offsets_at..edges_at], - edges: &self.data[edges_at..end], + edge_min: &self.edge_min[t as usize], + edge_row_at: &self.edge_row_at[t as usize], + edge_targets: &self.edge_targets[t as usize], }) } } @@ -307,21 +361,26 @@ impl<'a> StaticDFATable<'a> { } } - /// Successor of `state` on token type `t`, if any (binary search). + /// Successor of `state` on token type `t`, if any. O(1): the compact + /// serialized interval triples are expanded into a per-state direct- + /// indexed row at load time (see [`StaticDFATables::from_int_stream`]). #[inline] pub fn edge(&self, state: usize, t: i32) -> Option { - let mut lo = (self.edge_offsets[state] / 3) as usize; - let mut hi = (self.edge_offsets[state + 1] / 3) as usize; - while lo < hi { - let mid = lo + (hi - lo) / 2; - if t < self.edges[mid * 3] { - hi = mid; - } else if t > self.edges[mid * 3 + 1] { - lo = mid + 1; - } else { - return Some(self.edges[mid * 3 + 2] as usize); - } + let base = self.edge_row_at[state] as usize; + let end = self.edge_row_at[state + 1] as usize; + let idx = t - self.edge_min[state]; + if idx < 0 { + return None; + } + let pos = base + idx as usize; + if pos >= end { + return None; + } + let target = self.edge_targets[pos]; + if target < 0 { + None + } else { + Some(target as usize) } - None } } From 01aaaf1caeb7b3644763e988f7ec9017e473966d Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Sat, 25 Jul 2026 15:57:12 -0400 Subject: [PATCH 31/48] Rust static DFA: single per-state accepts load + debug-only escape tracing Two small follow-ups to the O(1)-edge change: - dfa_walk loaded accepts[s] twice per state (is_escape() then accept()). Load it once and drive both the escape (== ESCAPE) and accept (> 0) checks from it. ~2% off the per-decision static walk on 0-escape input. - Gate the ANTLR_DFA_TRACE machinery behind #[cfg(debug_assertions)]: in release dfa_trace() is a compile-time `false`, so every trace branch in the walk is eliminated; the debug build keeps the env-var check (now a LazyLock). Keeps diagnostics out of the shipped hot path. Note: the originally-planned advance-first reorder (try the edge before the accept/escape/mask checks) was measured and *reverted* - it regressed the 0-escape walk ~11% (133us baseline: step1 O(1)-edge -> 97us, reorder -> 109us). The three metadata checks are effectively free: the tables are L1-hot and the branches are perfectly predicted on intermediate states, so moving la()+edge() ahead only perturbed codegen. The residual ~1.08x vs warm adaptive on 0-escape input is inherent per-state cost, not the metadata checks. Measured (Trino, Rust release, warm, SELECT A,...,A FROM T, 300 cols): static 133us (pre-step1) -> 97us (step1) -> 96us (this); S/A 1.50 -> 1.08. cargo 11/11, runtime-testsuite rust.** 707/707, parsebench static-vs- adaptive diff over corpus-pred 318/0. Signed-off-by: Bo Lin --- runtime/Rust/src/parser.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index d1dcb2c4fd..e77e7012d5 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -514,10 +514,21 @@ where /// Diagnostic escape tracing for `dfa_predict` (`ANTLR_DFA_TRACE=1`): /// logs every prediction the static tables defer to the adaptive /// engine, the tool for finding which decisions a given input keeps - /// escaping on. Checked once per process. + /// escaping on. Debug builds only - in release it is a compile-time + /// `false` so every trace branch is eliminated from the hot walk. + #[cfg(debug_assertions)] fn dfa_trace() -> bool { - static TRACE: std::sync::OnceLock = std::sync::OnceLock::new(); - *TRACE.get_or_init(|| std::env::var_os("ANTLR_DFA_TRACE").is_some()) + static TRACE: std::sync::LazyLock = + std::sync::LazyLock::new(|| std::env::var_os("ANTLR_DFA_TRACE").is_some()); + *TRACE + } + + /// Release builds: tracing is compiled out entirely (see the + /// debug-build variant above). + #[cfg(not(debug_assertions))] + #[inline(always)] + fn dfa_trace() -> bool { + false } pub fn dfa_predict(&mut self, decision: i32) -> Result { @@ -728,7 +739,10 @@ where let mut s = 0usize; let mut i = 1isize; loop { - if dfa.is_escape(s) { + // One `accepts` load serves both the escape and accept checks + // (previously loaded twice, via is_escape() then accept()). + let alt = dfa.accepts[s]; + if alt == crate::static_dfa::ESCAPE { // hybrid-table escape: the caller reruns the prediction // through the adaptive engine (no input was consumed, so // the rescan starts clean) @@ -760,7 +774,7 @@ where } return Ok(mask); } - if let Some(alt) = dfa.accept(s) { + if alt > 0 { return Ok(1u64 << (alt - 1)); } let t = self.input.la(i); From 51b63c6c69b9596fc4de1e748b152bf050b4431c Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Tue, 28 Jul 2026 02:52:01 -0400 Subject: [PATCH 32/48] runtime-testsuite: isolate the two Rust suites from each other Running mvn -Dtest='rust.**' test executed RustRuntimeTests and RustStaticDFARuntimeTests as concurrent JUnit classes in one forked JVM (junit.jupiter.execution.parallel.mode.classes.default=concurrent), which made the combined command non-deterministic: - surefire 2.22.0 mis-attributes dynamic tests of interleaved classes: every combined run reported arbitrary splits (706/1, 700/7, 703/4) instead of 362/345, and any failure is charged to the wrong suite. - Both suites shared one on-disk build cache (/ANTLR-runtime-testsuite-cache/Rust): cargo clean during one configuration's runtime initialization deletes the rlib out from under the other configuration's rustc compiles whenever they overlap (concurrent classes, or concurrent Maven JVMs). Fixes: - @Execution(SAME_THREAD) on both Rust test classes so the suites never overlap in the forked JVM; tests within each suite still run concurrently via the @TestFactory's own @Execution(CONCURRENT). Other targets' class-level parallelism is unchanged. - New RuntimeRunner.getRuntimeConfigurationName() hook (defaults to the language) keying both the cache directory and the runtime initialization lock; RustStaticDFARunner overrides it to "Rust-static-dfa", giving each configuration its own cache and init. Verified: 4 consecutive combined runs all report exactly 362 + 345 tests with zero failures (previously every combined run mis-attributed). Signed-off-by: Bo Lin --- .../antlr/v4/test/runtime/RuntimeRunner.java | 22 ++++++++++++++----- .../test/runtime/rust/RustRuntimeTests.java | 12 ++++++++++ .../runtime/rust/RustStaticDFARunner.java | 12 ++++++++++ .../rust/RustStaticDFARuntimeTests.java | 10 +++++++++ 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeRunner.java index d1df8ae5fa..35434361bc 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeRunner.java @@ -143,8 +143,20 @@ private static class InitializationStatus { cacheDirectory = new File(System.getProperty("java.io.tmpdir"), "ANTLR-runtime-testsuite-cache").getAbsolutePath(); } + /** + * Identifies a distinct runner configuration sharing a language runtime + * (e.g. Rust with and without -Xstatic-dfa). Defaults to the language + * itself. Configurations get separate on-disk caches and separate + * initialization locks so that two configurations of one language can + * never clean or rebuild a cache directory out from under the other, + * even when run concurrently in the same or in separate JVMs. + */ + protected String getRuntimeConfigurationName() { + return getLanguage(); + } + protected final String getCachePath() { - return getCachePath(getLanguage()); + return getCachePath(getRuntimeConfigurationName()); } public static String getCachePath(String language) { @@ -268,15 +280,15 @@ protected void addExtraRecognizerParameters(ST template) { } private boolean initAntlrRuntimeIfRequired(RunOptions runOptions) { - String language = getLanguage(); + String configurationName = getRuntimeConfigurationName(); InitializationStatus status; - // Create initialization status for every runtime with lock object + // Create initialization status for every runtime configuration with lock object synchronized (runtimeInitializationStatuses) { - status = runtimeInitializationStatuses.get(language); + status = runtimeInitializationStatuses.get(configurationName); if (status == null) { status = new InitializationStatus(); - runtimeInitializationStatuses.put(language, status); + runtimeInitializationStatuses.put(configurationName, status); } } diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustRuntimeTests.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustRuntimeTests.java index cc87cc6d74..5eee5d676c 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustRuntimeTests.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustRuntimeTests.java @@ -8,7 +8,19 @@ import org.antlr.v4.test.runtime.RuntimeRunner; import org.antlr.v4.test.runtime.RuntimeTests; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +/** + * Runs the descriptor corpus against the Rust target with adaptive + * prediction. Executed {@link ExecutionMode#SAME_THREAD} so this suite never + * overlaps {@link RustStaticDFARuntimeTests} in the forked JVM: with + * concurrent classes, surefire 2.22.0 mis-attributes the two suites' + * dynamic tests to whichever class reports first (706/1-style splits), and + * any failure is reported against the wrong suite. Tests within the suite + * still run concurrently via the {@code @TestFactory}'s own annotation. + */ +@Execution(ExecutionMode.SAME_THREAD) public class RustRuntimeTests extends RuntimeTests { @Override protected RuntimeRunner createRuntimeRunner() { diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARunner.java index 68a2a7032b..4382829eeb 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARunner.java @@ -18,6 +18,18 @@ * prediction, so any deviation of the table-driven path fails the test. */ public class RustStaticDFARunner extends RustRunner { + /** + * Keep this configuration's build cache separate from the adaptive + * suite's: both otherwise share {@code /ANTLR-runtime-testsuite-cache/Rust}, + * where {@code cargo clean} during one suite's runtime initialization can + * delete the rlib out from under the other suite's compiles when they + * overlap (same JVM with concurrent classes, or concurrent Maven JVMs). + */ + @Override + protected String getRuntimeConfigurationName() { + return "Rust-static-dfa"; + } + @Override protected List getTargetToolOptions(RunOptions ro) { List options = super.getTargetToolOptions(ro); diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARuntimeTests.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARuntimeTests.java index 7f5c3eec8b..565d532075 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARuntimeTests.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/rust/RustStaticDFARuntimeTests.java @@ -9,6 +9,8 @@ import org.antlr.v4.test.runtime.RuntimeRunner; import org.antlr.v4.test.runtime.RuntimeTestDescriptor; import org.antlr.v4.test.runtime.RuntimeTests; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; /** * Runs the full runtime-test descriptor corpus against the Rust target with @@ -23,7 +25,15 @@ * {@code adaptive_predict}, which statically-decided decisions bypass by * design (a trusted exact ambiguity, for example, is resolved to its minimum * alternative by the table without a runtime ambiguity report).

+ * + *

Executed {@link ExecutionMode#SAME_THREAD} so this suite never overlaps + * {@link RustRuntimeTests} in the forked JVM (see that class for why), and + * its runner uses a separate build-cache directory + * ({@link RustStaticDFARunner#getRuntimeConfigurationName()}) so the two + * suites cannot clobber each other's compiled runtime even across + * concurrent Maven JVMs.

*/ +@Execution(ExecutionMode.SAME_THREAD) public class RustStaticDFARuntimeTests extends RuntimeTests { @Override protected RuntimeRunner createRuntimeRunner() { From 9628bc981da9ee16d669c0a0c6adb62043b3637f Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Tue, 28 Jul 2026 06:08:46 -0400 Subject: [PATCH 33/48] Guarded-take escape: stack-guarded static resolution of optional-postfix conflicts The optional-postfix take rule (X Y?, dangling-else) vetoes when a skip configuration leaves the mirror discipline - a boundary follow-chase whose consumption is not funneled through the decision's own take path. Some vetoes are genuinely context-sensitive yet almost always resolvable: Bigquery's pred=predicate? decision (d=309) must answer skip inside MERGE ... UPDATE SET targets+=expression EQ values+=expression (verified empirically: adaptivePredict parses SET a = b as target/EQ/value) but take everywhere else, so no context-free static answer exists - the vetoed states escaped to adaptivePredict on every WHERE/HAVING/ON comparison, costing the dialect its entire static-DFA win. This change resolves such conflicts to take guarded by a runtime stack test (table format v7): - DecisionClassifier marks skip-lineage consumption outside the dangling-else discipline with ROOTED_TAINT and records guard roots (the consumption position for EMPTY-bottomed contexts, the call site of a non-mirror deepest context frame otherwise), propagated per DFA state to a fixpoint. A vetoed conflict whose skip configs are all in-discipline, mirror-bottomed, or rooted - none widening-born - resolves to take, emitting the root set as the decision's guard. Bails: clean out-of-discipline skip config, always-firing guard (root epsilon-reachable from the block end), or never-firing guard (block end cannot reach the rule stop; downgrades to plain takes). Rooted-tainted conflicts are never trusted as exact ambiguities (a max-merge may hide a hard bit beneath ROOTED_TAINT). - The guard evaluates the epsilon-pop chase from the decision's block end over the real parse stack: defer to adaptivePredict iff some invoking state's follow region epsilon-reaches a guard root (danger set), stopping the walk at the first invoking state whose follow cannot reach its own rule's stop (pass set). Both sets are precomputed per decision and serialized as sorted arrays. - Java and Rust runtimes implement the GUARDED accept (-3) in their table walkers; format v7 serializes per-state guarded alts plus the danger/pass sets. Only Java and Rust targets support static tables. - Witness: grammars/GuardExpr.g4 + guard_differential_tests.rs - the assignment/comparison dangling-else (37 corners), exercising both guard-take and guard-defer directions (10 each under ANTLR_DFA_TRACE). Census: 380 guarded takes across six SQL dialects (Duckdb 157, Redshift 141, Snowflake 64, Bigquery 12, Databricks 5). Bigquery d=309: 12 of 13 vetoed states guarded, roots = {mergeUpdateClause EQ sites, pivotOperator IN site}. Verification: cargo 12/12 (witnesses regenerated byte-deterministically to v7), tool-testsuite 694/694, runtime-testsuite rust.** 707/707, corpus differentials 3208 queries/dialect - Duckdb 0 mismatches, Trino 2 and Bigquery 3 (all proven pre-existing '::' error-path divergences by re-running the pre-guard tool). Rust MERGE/CASE/ORDER-BY/parens parity battery 10/10. Perf (Rust, release): Bigquery predicate-heavy queries 1.6-2.6x static vs adaptive (was ~1.0x), Duckdb 1.1-2.2x. Signed-off-by: Bo Lin --- .../Java/src/org/antlr/v4/runtime/Parser.java | 11 + .../antlr/v4/runtime/atn/StaticDFATables.java | 81 +- runtime/Rust/gen_test_grammars.sh | 8 + runtime/Rust/grammars/GuardExpr.g4 | 49 + runtime/Rust/src/parser.rs | 48 + runtime/Rust/src/static_dfa.rs | 107 +- .../gen/adaptive/guardexprbaselistener.rs | 131 ++ .../Rust/tests/gen/adaptive/guardexprlexer.rs | 142 ++ .../tests/gen/adaptive/guardexprlistener.rs | 108 + .../tests/gen/adaptive/guardexprparser.rs | 1806 ++++++++++++++++ runtime/Rust/tests/gen/betweenexprparser.rs | 16 +- runtime/Rust/tests/gen/fuzzexprparser.rs | 20 +- .../Rust/tests/gen/guardexprbaselistener.rs | 131 ++ runtime/Rust/tests/gen/guardexprlexer.rs | 142 ++ runtime/Rust/tests/gen/guardexprlistener.rs | 108 + runtime/Rust/tests/gen/guardexprparser.rs | 1820 +++++++++++++++++ runtime/Rust/tests/gen/lrdfaparser.rs | 15 +- runtime/Rust/tests/gen/parenexprparser.rs | 8 +- runtime/Rust/tests/gen/staticdfaparser.rs | 8 +- .../Rust/tests/guard_differential_tests.rs | 141 ++ .../antlr/v4/analysis/DecisionClassifier.java | 417 +++- tool/src/org/antlr/v4/analysis/StaticDFA.java | 44 +- .../codegen/model/SerializedStaticDFAs.java | 70 +- 23 files changed, 5362 insertions(+), 69 deletions(-) create mode 100644 runtime/Rust/grammars/GuardExpr.g4 create mode 100644 runtime/Rust/tests/gen/adaptive/guardexprbaselistener.rs create mode 100644 runtime/Rust/tests/gen/adaptive/guardexprlexer.rs create mode 100644 runtime/Rust/tests/gen/adaptive/guardexprlistener.rs create mode 100644 runtime/Rust/tests/gen/adaptive/guardexprparser.rs create mode 100644 runtime/Rust/tests/gen/guardexprbaselistener.rs create mode 100644 runtime/Rust/tests/gen/guardexprlexer.rs create mode 100644 runtime/Rust/tests/gen/guardexprlistener.rs create mode 100644 runtime/Rust/tests/gen/guardexprparser.rs create mode 100644 runtime/Rust/tests/guard_differential_tests.rs diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java index 19ddff8a58..598b761f05 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java @@ -566,6 +566,17 @@ public int dfaPredict(StaticDFATables tables, int decision) while (true) { int alt = tables.accept(table, s); if ( alt>0 ) return alt; + if ( alt==StaticDFATables.GUARDED ) { + // guarded take of an optional-postfix decision: resolve to + // take unless the real parse stack's epsilon-pop chase from + // the decision's block end can reach a guard root + if ( !tables.guardDefers(table, _ctx) ) return tables.guardedAlt(table, s); + if ( System.getProperty("antlr.dfa.trace") != null ) { + System.err.println("DFA-TRACE guard-defer" + +" d="+decision+" prec="+getPrecedence()+" state="+s+" la1="+_input.LA(1)); + } + return getInterpreter().adaptivePredict(_input, decision, _ctx); + } if ( alt<0 ) { // hybrid-table escape (-1) or mask-accept state (-2; Java // has no factored codegen): rerun the prediction through diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java index 47bac1bf22..ce7acf5e51 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/StaticDFATables.java @@ -60,12 +60,18 @@ */ public class StaticDFATables { /** Must match the tool's SerializedStaticDFAs.FORMAT_VERSION. */ - public static final int FORMAT_VERSION = 6; + public static final int FORMAT_VERSION = 7; /** Concatenated per-table data: accepts, fallbacks, edgeOffsets, edges. */ protected final int[] data; /** Per-table (acceptsAt, fallbacksAt, edgeOffsetsAt, edgesAt, endAt) indexes into {@link #data}. */ protected final int[] metas; + /** Per-table guarded-take resolution alt per state (0 = not guarded). */ + protected final int[][] guardedAlts; + /** Per-table sorted invoking states tripping the decision's stack guard. */ + protected final int[][] guardDanger; + /** Per-table sorted invoking states the guard walk may pop past. */ + protected final int[][] guardPass; /** * decision number -> table index ({@code >= 0}), -1 (no table), or * {@code -(dispatch offset) - 2}: an offset into {@link #dispatchData}, @@ -76,11 +82,15 @@ public class StaticDFATables { /** Flattened precedence dispatch entries. */ protected final int[] dispatchData; - protected StaticDFATables(int[] data, int[] metas, int[] decisionToTable, int[] dispatchData) { + protected StaticDFATables(int[] data, int[] metas, int[] decisionToTable, int[] dispatchData, + int[][] guardedAlts, int[][] guardDanger, int[][] guardPass) { this.data = data; this.metas = metas; this.decisionToTable = decisionToTable; this.dispatchData = dispatchData; + this.guardedAlts = guardedAlts; + this.guardDanger = guardDanger; + this.guardPass = guardPass; } /** @@ -107,6 +117,9 @@ public static StaticDFATables deserialize(String[] segments) { int[] decisionToTable = new int[numSlots]; java.util.Arrays.fill(decisionToTable, -1); int[] metas = new int[numTables*5]; + int[][] guardedAlts = new int[numTables][]; + int[][] guardDanger = new int[numTables][]; + int[][] guardPass = new int[numTables][]; // first pass over structure requires data sizes; buffer grows as we read IntBuffer data = new IntBuffer(); @@ -137,6 +150,29 @@ public static StaticDFATables deserialize(String[] segments) { for (int a = 0; a < numAlts; a++) ints.next(); data.set(metas[table*5]+state, MASK_DEFER); } + // v7: guarded-take section (optional-postfix guards) + int numGuardedStates = ints.next(); + if (numGuardedStates > 0) { + int[] alts = new int[numStates]; + for (int i = 0; i < numGuardedStates; i++) { + int state = ints.next(); + alts[state] = ints.next(); + data.set(metas[table*5]+state, GUARDED); + } + guardedAlts[table] = alts; + } + int numDanger = ints.next(); + if (numDanger > 0) { + int[] danger = new int[numDanger]; + for (int i = 0; i < numDanger; i++) danger[i] = ints.next(); + guardDanger[table] = danger; + } + int numPass = ints.next(); + if (numPass > 0) { + int[] pass = new int[numPass]; + for (int i = 0; i < numPass; i++) pass[i] = ints.next(); + guardPass[table] = pass; + } metas[table*5+4] = data.size; // endAt } int numDispatches = ints.next(); @@ -151,7 +187,8 @@ public static StaticDFATables deserialize(String[] segments) { if (!ints.atEnd()) { throw new IllegalStateException("trailing bytes in static DFA blob"); } - return new StaticDFATables(data.toArray(), metas, decisionToTable, dispatchData.toArray()); + return new StaticDFATables(data.toArray(), metas, decisionToTable, dispatchData.toArray(), + guardedAlts, guardDanger, guardPass); } /** {@code accepts} sentinel: a hybrid table's escape state - the walker @@ -163,6 +200,14 @@ public static StaticDFATables deserialize(String[] segments) { * runtime resolves the mask through its factored alternative path. */ public static final int MASK_DEFER = -2; + /** {@code accepts} sentinel: a guarded-take state of an + * optional-postfix decision: the walker evaluates the decision's + * stack guard ({@link #guardDefers}) and resolves to + * {@link #guardedAlt} when it passes, deferring to + * {@code adaptivePredict} when the stack trips a danger invoking + * state. */ + public static final int GUARDED = -3; + /** * Is {@code decision} precedence-dispatched (per-precedence-class * tables of a left-recursive loop)? Such tables are built against the @@ -231,6 +276,36 @@ public int edge(int table, int state, int t) { return -1; } + /** Resolution alternative of a {@link #GUARDED} state. */ + public int guardedAlt(int table, int state) { + return guardedAlts[table][state]; + } + + /** + * The stack guard of a guarded-take state: walk the parse stack's + * invoking states - the epsilon-pop chase from the decision's block + * end - and answer whether the prediction must defer to + * {@code adaptivePredict}: an invoking state whose follow region + * contains a guard root ({@code danger}) trips it; an invoking state + * whose follow cannot reach its own rule's stop ends the chase (the + * configurations it could still realize are confined to the mirror + * discipline); anything else keeps walking. + */ + public boolean guardDefers(int table, org.antlr.v4.runtime.RuleContext ctx) { + int[] danger = guardDanger[table]; + int[] pass = guardPass[table]; + for (org.antlr.v4.runtime.RuleContext c = ctx; + c instanceof org.antlr.v4.runtime.ParserRuleContext; + c = c.parent) + { + int inv = ((org.antlr.v4.runtime.ParserRuleContext)c).invokingState; + if (inv < 0) break; + if (java.util.Arrays.binarySearch(danger, inv) >= 0) return true; + if (java.util.Arrays.binarySearch(pass, inv) < 0) break; + } + return false; + } + private static final class IntReader { final byte[] bytes; int at; diff --git a/runtime/Rust/gen_test_grammars.sh b/runtime/Rust/gen_test_grammars.sh index 4e3f1dfa1e..47439c456a 100755 --- a/runtime/Rust/gen_test_grammars.sh +++ b/runtime/Rust/gen_test_grammars.sh @@ -18,6 +18,7 @@ declare -a GRAMMARS=( "FuzzExpr" "BetweenExpr" "ParenExpr" + "GuardExpr" # "FHIRPath" ) @@ -34,6 +35,7 @@ declare -a ADDITIONAL_ARGS=( "-Xstatic-dfa" "-Xstatic-dfa" "-Xstatic-dfa" + "-Xstatic-dfa" ) for i in "${!GRAMMARS[@]}"; do @@ -68,3 +70,9 @@ echo "Generating: BetweenExpr (adaptive twin)" echo "Generating: ParenExpr (adaptive twin)" (cd "$SCRIPT_DIR/grammars" && java -cp "$ANTLR_PATH" org.antlr.v4.Tool -Dlanguage=Rust \ -o ../tests/gen/adaptive ParenExpr.g4) + +# Same differential twin for the guarded-take grammar +# (tests/guard_differential_tests.rs). +echo "Generating: GuardExpr (adaptive twin)" +(cd "$SCRIPT_DIR/grammars" && java -cp "$ANTLR_PATH" org.antlr.v4.Tool -Dlanguage=Rust \ + -o ../tests/gen/adaptive GuardExpr.g4) diff --git a/runtime/Rust/grammars/GuardExpr.g4 b/runtime/Rust/grammars/GuardExpr.g4 new file mode 100644 index 0000000000..aa4eb89788 --- /dev/null +++ b/runtime/Rust/grammars/GuardExpr.g4 @@ -0,0 +1,49 @@ +// Differential-test grammar isolating the guarded-take escape of the +// optional-postfix take rule, in the exact shape the dbt SQL grammars +// carry it (Bigquery's `UPDATE SET targets+=expression EQ +// values+=expression` vs `expression: valueExpression predicate?`): +// +// expr : value pred? # the X Y? postfix decision +// stmt : 'set' expr '=' expr # a caller where skip genuinely wins +// | expr # callers where take genuinely wins +// +// After `set a`, the pred? decision sees '=': take reads `a = b` as a +// comparison (then the assignment's own '=' is missing - dead end), skip +// closes the target expression and lets the assignment's '=' through. +// Which reading survives depends on the CALL STACK (inside an assignment +// target vs everywhere else), so the decision's take/skip conflict is +// genuinely context-sensitive: the static table resolves it to take +// guarded by a stack test that defers to adaptivePredict exactly when an +// invoking state of the assignment's `expr` call is present (the +// epsilon-pop chase from the decision's block end reaches the +// assignment's '=' position). Everywhere else take resolves statically. +// +// The chase must STOP at constructs that seal the expression off from +// the assignment: parentheses ('(' expr ')'), the IN list, and the right +// operand of a boolean operator whose parent chain never enters an +// assignment - inside those, `a = b` is a comparison even when the whole +// thing sits in an assignment value (`set x = (a = b)` is an assignment +// of a comparison, not a nested assignment). +grammar GuardExpr; + +prog : stmt+ EOF ; + +stmt : 'set' expr '=' expr ';' # assign + | expr ';' # eval + ; + +expr : value pred? # predicated + | 'NOT' expr # not + | expr 'AND' expr # and + | expr 'OR' expr # or + ; + +pred : ('='|'<'|'>') value # cmp + | 'IN' '(' expr ')' # inList + ; + +value : ID | INT | '(' expr ')' ; + +ID : [a-z]+ ; +INT : [0-9]+ ; +WS : [ \t\n]+ -> skip ; diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index e77e7012d5..d18ecca43c 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -758,6 +758,54 @@ where } return Ok(0); } + if alt == crate::static_dfa::GUARDED { + // guarded take of an optional-postfix decision: resolve + // to take unless the real parse stack's epsilon-pop + // chase from the decision's block end can reach a guard + // root (an invoking state in the table's danger set); + // the walk stops at the first invoking state whose + // follow region cannot reach its own rule's stop. + let mut defers = false; + let mut c = self.ctx(); + while let Some(node) = c { + let inv = node.get_invoking_state(); + if inv < 0 { + break; + } + match dfa.guard_step(inv) { + Some(true) => { + defers = true; + break; + } + Some(false) => break, + None => c = node.get_parent(), + } + } + if !defers { + if Self::dfa_trace() { + eprintln!( + "DFA-TRACE guard-take d={} prec={} state={} depth={} la1={}", + decision, + precedence, + s, + i - 1, + self.input.la(1) + ); + } + return Ok(1u64 << (dfa.guarded_alt(s).unwrap() - 1)); + } + if Self::dfa_trace() { + eprintln!( + "DFA-TRACE guard-defer d={} prec={} state={} depth={} la1={}", + decision, + precedence, + s, + i - 1, + self.input.la(1) + ); + } + return Ok(0); + } if let Some(mask) = dfa.accept_mask(s) { // mask-accept: the live alternatives are covered by one // prefix-factor group diff --git a/runtime/Rust/src/static_dfa.rs b/runtime/Rust/src/static_dfa.rs index f26837155a..d30b821f66 100644 --- a/runtime/Rust/src/static_dfa.rs +++ b/runtime/Rust/src/static_dfa.rs @@ -29,6 +29,20 @@ //! fallbacks[numStates] (error-avoidance alt per state; 0 = none) //! edgeOffsets[numStates+1] (index of each state's first edge i32) //! edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) +//! numMaskStates (alternative-mask accepts; v6) +//! for each mask state: +//! state, numAlts, alts[numAlts] +//! numGuardedStates (guarded-take states of an +//! optional-postfix decision; v7: the walker +//! evaluates the decision's stack guard and +//! resolves to the given alternative when it +//! passes, deferring to adaptive prediction +//! when the stack trips a danger state) +//! for each guarded state: (sorted by state index) +//! state, alt +//! numDanger, danger[numDanger] (sorted invoking states tripping the guard) +//! numPass, pass[numPass] (sorted invoking states the guard walk +//! pops past) //! numPrecedenceDispatches //! for each dispatch: (a left-recursive precedence loop decision) //! decision @@ -48,8 +62,9 @@ /// Format version understood by this runtime; must match the tool's /// `SerializedStaticDFAs.FORMAT_VERSION`. v6 adds the per-table -/// alternative-mask section (prefix-factor groups). -pub const FORMAT_VERSION: i32 = 6; +/// alternative-mask section (prefix-factor groups); v7 adds the +/// per-table guarded-take section (optional-postfix stack guards). +pub const FORMAT_VERSION: i32 = 7; /// The deserialized static prediction tables of one generated parser. /// @@ -71,6 +86,16 @@ pub struct StaticDFATables { /// Per-table alternative-mask accepts (bit 1<<(alt-1) per live /// alternative of the covering prefix-factor group; 0 = none). masks: Vec>, + /// Per-table guarded-take resolution alt per state (0 = not guarded); + /// absent for tables without guarded states. + guarded_alts: Vec>>, + /// Per-table sorted invoking states tripping the decision's stack + /// guard (its epsilon-pop chase can reach a guard root past them). + guard_danger: Vec>, + /// Per-table sorted invoking states whose follow region reaches their + /// own rule's stop over epsilon; the guard walk pops past them and + /// stops at the first invoking state not listed. + guard_pass: Vec>, /// decision number -> table index (`>= 0`), `-1` (no table), or /// `-(dispatch index) - 2` (precedence-dispatched decision). decision_to_table: Vec, @@ -106,6 +131,13 @@ pub struct StaticDFATable<'a> { /// more precise error at the mismatch point - mirroring /// `adaptive_predict`'s finished-decision-entry-rule recovery. pub fallbacks: &'a [i32], + /// Guarded-take resolution alt per state; `None` for tables without + /// guarded states (entry 0 = not guarded). + pub guarded_alts: Option<&'a [i32]>, + /// Sorted invoking states tripping this decision's stack guard. + pub guard_danger: &'a [i32], + /// Sorted invoking states the guard walk may pop past. + pub guard_pass: &'a [i32], /// State `s`'s base token: `edge()` indexes `edge_targets` at /// `edge_row_at[s] + (t - edge_min[s])`. pub edge_min: &'a [i32], @@ -125,6 +157,9 @@ impl StaticDFATables { data: Vec::new(), metas: Vec::new(), masks: Vec::new(), + guarded_alts: Vec::new(), + guard_danger: Vec::new(), + guard_pass: Vec::new(), decision_to_table: Vec::new(), dispatch_data: Vec::new(), dispatch_at: Vec::new(), @@ -157,6 +192,9 @@ impl StaticDFATables { let mut data = Vec::new(); let mut metas = Vec::with_capacity(num_tables); let mut masks = Vec::with_capacity(num_tables); + let mut guarded_alts = Vec::with_capacity(num_tables); + let mut guard_danger = Vec::with_capacity(num_tables); + let mut guard_pass = Vec::with_capacity(num_tables); let mut edge_min: Vec> = Vec::with_capacity(num_tables); let mut edge_row_at: Vec> = Vec::with_capacity(num_tables); let mut edge_targets: Vec> = Vec::with_capacity(num_tables); @@ -235,6 +273,31 @@ impl StaticDFATables { table_masks[state] = bits; } masks.push(table_masks); + // v7: guarded-take section + let num_guarded_states = next() as usize; + let mut table_guarded = None; + if num_guarded_states > 0 { + let mut alts = vec![0i32; num_states]; + for _ in 0..num_guarded_states { + let state = next() as usize; + alts[state] = next(); + data[accepts_at + state] = GUARDED; + } + table_guarded = Some(alts); + } + guarded_alts.push(table_guarded); + let num_danger = next() as usize; + let mut danger = Vec::with_capacity(num_danger); + for _ in 0..num_danger { + danger.push(next()); + } + guard_danger.push(danger); + let num_pass = next() as usize; + let mut pass = Vec::with_capacity(num_pass); + for _ in 0..num_pass { + pass.push(next()); + } + guard_pass.push(pass); metas.push((accepts_at, fallbacks_at, edge_offsets_at, edges_at)); } @@ -258,6 +321,9 @@ impl StaticDFATables { data, metas, masks, + guarded_alts, + guard_danger, + guard_pass, decision_to_table, dispatch_data, dispatch_at, @@ -306,6 +372,9 @@ impl StaticDFATables { accepts: &self.data[accepts_at..fallbacks_at], masks: &self.masks[t as usize], fallbacks: &self.data[fallbacks_at..edge_offsets_at], + guarded_alts: self.guarded_alts[t as usize].as_deref(), + guard_danger: &self.guard_danger[t as usize], + guard_pass: &self.guard_pass[t as usize], edge_min: &self.edge_min[t as usize], edge_row_at: &self.edge_row_at[t as usize], edge_targets: &self.edge_targets[t as usize], @@ -318,6 +387,14 @@ impl StaticDFATables { /// consumes input, so the rescan is trivially sound). pub const ESCAPE: i32 = -1; +/// `accepts` sentinel: a guarded-take state of an optional-postfix +/// decision (`X Y?`): the walker evaluates the decision's stack guard +/// (the epsilon-pop chase from the decision's block end over the real +/// parse stack) and resolves to the state's guarded alt when it passes, +/// deferring to the adaptive engine when an invoking state on the stack +/// trips the guard's danger set. +pub const GUARDED: i32 = -3; + impl<'a> StaticDFATable<'a> { /// Predicted alternative if `state` is an accept state. #[inline] @@ -337,6 +414,32 @@ impl<'a> StaticDFATable<'a> { self.accepts[state] == ESCAPE } + /// Guarded-take resolution of `state`: `Some(alt)` when it is a + /// guarded-take state (see [`GUARDED`]). The walker still has to + /// evaluate the stack guard (see + /// [`crate::parser::BaseParser::dfa_walk`]). + #[inline] + pub fn guarded_alt(&self, state: usize) -> Option { + match self.guarded_alts { + Some(alts) if alts[state] > 0 => Some(alts[state]), + _ => None, + } + } + + /// Guard walk step: `Some(true)` = the invoking state trips the + /// guard (defer to the adaptive engine); `Some(false)` = the chase + /// ends here (resolve to take); `None` = keep walking the stack. + #[inline] + pub fn guard_step(&self, invoking_state: i32) -> Option { + if self.guard_danger.binary_search(&invoking_state).is_ok() { + Some(true) + } else if self.guard_pass.binary_search(&invoking_state).is_err() { + Some(false) + } else { + None + } + } + /// Alternative mask of `state` when it mask-accepts (the live /// alternatives are covered by one prefix-factor group; bit /// `1<<(alt-1)` per member). diff --git a/runtime/Rust/tests/gen/adaptive/guardexprbaselistener.rs b/runtime/Rust/tests/gen/adaptive/guardexprbaselistener.rs new file mode 100644 index 0000000000..edf77eaf17 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/guardexprbaselistener.rs @@ -0,0 +1,131 @@ +// Generated from GuardExpr.g4 by ANTLR 4.13.2 + +use super::guardexprparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by GuardExprParser. + +pub trait GuardExprBaseListener<'arena>: + ParseTreeListener<'arena, GuardExprParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_prog(&mut self, _ctx: &ProgContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_prog(&mut self, _ctx: &ProgContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_assign(&mut self, _ctx: &AssignContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_assign(&mut self, _ctx: &AssignContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_eval(&mut self, _ctx: &EvalContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_eval(&mut self, _ctx: &EvalContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_not(&mut self, _ctx: &NotContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_not(&mut self, _ctx: &NotContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_predicated(&mut self, _ctx: &PredicatedContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_predicated(&mut self, _ctx: &PredicatedContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_or(&mut self, _ctx: &OrContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_or(&mut self, _ctx: &OrContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_and(&mut self, _ctx: &AndContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_and(&mut self, _ctx: &AndContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_cmp(&mut self, _ctx: &CmpContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_cmp(&mut self, _ctx: &CmpContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_inlist(&mut self, _ctx: &InListContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_inlist(&mut self, _ctx: &InListContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_value(&mut self, _ctx: &ValueContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_value(&mut self, _ctx: &ValueContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/adaptive/guardexprlexer.rs b/runtime/Rust/tests/gen/adaptive/guardexprlexer.rs new file mode 100644 index 0000000000..31533c85cb --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/guardexprlexer.rs @@ -0,0 +1,142 @@ +// Generated from GuardExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const T__8:i32=9; +pub const T__9:i32=10; +pub const T__10:i32=11; +pub const ID:i32=12; +pub const INT:i32=13; +pub const WS:i32=14; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;14] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "ID", "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;12] = [ + None, Some("'set'"), Some("'='"), Some("';'"), Some("'NOT'"), Some("'AND'"), + Some("'OR'"), Some("'<'"), Some("'>'"), Some("'IN'"), Some("'('"), Some("')'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;15] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, GuardExprLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct GuardExprLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { GuardExprLexer } +dbt_antlr4::impl_deref! { lexer => GuardExprLexer } + +impl<'input, 'arena, Input, TF> GuardExprLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = GuardExprLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct GuardExprLexerActions { +} + +impl GuardExprLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for GuardExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for GuardExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "GuardExprLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 13] = [ + "CAAcmAEMAQQADgAEAg4CBAQOBAQGDgYECA4IBAoOCgQMDgwEDg4OBBAOEAQSDhIEFA4UBBYOFgQYDhgE", + "Gg4aAgACAAIAAgACAgICAgQCBAIGAgYCBgIGAggCCAIIAggCCgIKAgoCDAIMAg4CDgIQAhACEAISAhIC", + "FAIUAhYIFnoQFhYWGBZ8AhgIGIQBEBgWGBgYhgECGggajgEQGhYaGBqQAQIaAhoAABwCAgYECgYOCBIK", + "FgwaDh4QIhImFCoWLhgyGjYcAgAGAgDCAfQBAgBgcgQAEhRAQJwBAAICAAAAAAYCAAAAAAoCAAAAAA4C", + "AAAAABICAAAAABYCAAAAABoCAAAAAB4CAAAAACICAAAAACYCAAAAACoCAAAAAC4CAAAAADICAAAAADYC", + "AAAAAjoCAAAABkICAAAACkYCAAAADkoCAAAAElICAAAAFloCAAAAGmACAAAAHmQCAAAAImgCAAAAJm4C", + "AAAAKnICAAAALngCAAAAMoIBAgAAADaMAQIAAAA6PArmAQAAPD4KygEAAD5ACugBAABABAIAAABCRAp6", + "AABECAIAAABGSAp2AABIDAIAAABKTAqcAQAATE4KngEAAE5QCqgBAABQEAIAAABSVAqCAQAAVFYKnAEA", + "AFZYCogBAABYFAIAAABaXAqeAQAAXF4KpAEAAF4YAgAAAGBiCngAAGIcAgAAAGRmCnwAAGYgAgAAAGhq", + "CpIBAABqbAqcAQAAbCQCAAAAbnAKUAAAcCgCAAAAcnQKUgAAdCwCAAAAdnoOAAAAeHYCAAAAenwCAAAA", + "fHgCAAAAfH4CAAAAfjACAAAAgAGEAQ4CAACCAYABAgAAAIQBhgECAAAAhgGCAQIAAACGAYgBAgAAAIgB", + "NAIAAACKAY4BDgQAAIwBigECAAAAjgGQAQIAAACQAYwBAgAAAJABkgECAAAAkgGUAQIAAACUAZYBDBoA", + "AJYBOAIAAAAIAHyGAZABAgwAAA==" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/adaptive/guardexprlistener.rs b/runtime/Rust/tests/gen/adaptive/guardexprlistener.rs new file mode 100644 index 0000000000..e5226c7745 --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/guardexprlistener.rs @@ -0,0 +1,108 @@ +#![allow(nonstandard_style)] +// Generated from GuardExpr.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::guardexprparser::*; + +pub trait GuardExprListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, GuardExprParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link GuardExprParser#prog}. + /// @param ctx the parse tree + fn enter_prog<'input: 'arena>(&mut self, _ctx: &ProgContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link GuardExprParser#prog}. + /// @param ctx the parse tree + fn exit_prog<'input: 'arena>(&mut self, _ctx: &ProgContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code assign} + /// labeled alternative in {@link GuardExprParser#stmt}. + /// @param ctx the parse tree + fn enter_assign<'input: 'arena>(&mut self, _ctx: &AssignContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code assign} + /// labeled alternative in {@link GuardExprParser#stmt}. + /// @param ctx the parse tree + fn exit_assign<'input: 'arena>(&mut self, _ctx: &AssignContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code eval} + /// labeled alternative in {@link GuardExprParser#stmt}. + /// @param ctx the parse tree + fn enter_eval<'input: 'arena>(&mut self, _ctx: &EvalContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code eval} + /// labeled alternative in {@link GuardExprParser#stmt}. + /// @param ctx the parse tree + fn exit_eval<'input: 'arena>(&mut self, _ctx: &EvalContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code not} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn enter_not<'input: 'arena>(&mut self, _ctx: &NotContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code not} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn exit_not<'input: 'arena>(&mut self, _ctx: &NotContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code predicated} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn enter_predicated<'input: 'arena>(&mut self, _ctx: &PredicatedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code predicated} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn exit_predicated<'input: 'arena>(&mut self, _ctx: &PredicatedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code or} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn enter_or<'input: 'arena>(&mut self, _ctx: &OrContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code or} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn exit_or<'input: 'arena>(&mut self, _ctx: &OrContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code and} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn enter_and<'input: 'arena>(&mut self, _ctx: &AndContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code and} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn exit_and<'input: 'arena>(&mut self, _ctx: &AndContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code cmp} + /// labeled alternative in {@link GuardExprParser#pred}. + /// @param ctx the parse tree + fn enter_cmp<'input: 'arena>(&mut self, _ctx: &CmpContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code cmp} + /// labeled alternative in {@link GuardExprParser#pred}. + /// @param ctx the parse tree + fn exit_cmp<'input: 'arena>(&mut self, _ctx: &CmpContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code inList} + /// labeled alternative in {@link GuardExprParser#pred}. + /// @param ctx the parse tree + fn enter_inList<'input: 'arena>(&mut self, _ctx: &InListContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code inList} + /// labeled alternative in {@link GuardExprParser#pred}. + /// @param ctx the parse tree + fn exit_inList<'input: 'arena>(&mut self, _ctx: &InListContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link GuardExprParser#value}. + /// @param ctx the parse tree + fn enter_value<'input: 'arena>(&mut self, _ctx: &ValueContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link GuardExprParser#value}. + /// @param ctx the parse tree + fn exit_value<'input: 'arena>(&mut self, _ctx: &ValueContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/adaptive/guardexprparser.rs b/runtime/Rust/tests/gen/adaptive/guardexprparser.rs new file mode 100644 index 0000000000..2195cef06d --- /dev/null +++ b/runtime/Rust/tests/gen/adaptive/guardexprparser.rs @@ -0,0 +1,1806 @@ +// Generated from GuardExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::guardexprlistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const GuardExpr_T__0:i32=1; +pub const GuardExpr_T__1:i32=2; +pub const GuardExpr_T__2:i32=3; +pub const GuardExpr_T__3:i32=4; +pub const GuardExpr_T__4:i32=5; +pub const GuardExpr_T__5:i32=6; +pub const GuardExpr_T__6:i32=7; +pub const GuardExpr_T__7:i32=8; +pub const GuardExpr_T__8:i32=9; +pub const GuardExpr_T__9:i32=10; +pub const GuardExpr_T__10:i32=11; +pub const GuardExpr_ID:i32=12; +pub const GuardExpr_INT:i32=13; +pub const GuardExpr_WS:i32=14; +pub const GuardExpr_EOF:i32=EOF; +pub const RULE_prog:usize = 0; +pub const RULE_stmt:usize = 1; +pub const RULE_expr:usize = 2; +pub const RULE_pred:usize = 3; +pub const RULE_value:usize = 4; +pub const ruleNames: [&'static str; 5] = [ + "prog", "stmt", "expr", "pred", "value" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;12] = [ + None, Some("'set'"), Some("'='"), Some("';'"), Some("'NOT'"), Some("'AND'"), + Some("'OR'"), Some("'<'"), Some("'>'"), Some("'IN'"), Some("'('"), Some("')'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;15] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, GuardExprParserExt<'input, 'arena>, GuardExprParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + GuardExprParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: GuardExprListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct GuardExprTreeWalker; +impl GuardExprTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: GuardExprListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, GuardExprParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum GuardExprParserNodeKind { + ProgContext, + StmtContext, + ExprContext, + PredContext, + ValueContext, + Terminal, + Error, +} +pub type GuardExprParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, GuardExprParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => GuardExprParser } +dbt_antlr4::impl_node_kind! { GuardExprParserNodeKind { + StmtContext(StmtContextAll), ExprContext(ExprContextAll), PredContext(PredContextAll), ; ProgContext(enter_prog, exit_prog, ), ValueContext(enter_value, exit_value, ), + }; listener = dyn GuardExprListener<'arena, Tok>, +} + +pub struct GuardExprParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> GuardExprParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for GuardExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for GuardExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "GuardExpr.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena GuardExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 2 => GuardExprParser::<'input, 'arena, Input, TF>::expr_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn expr_sempred(_ctx: Option<&'arena ExprContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 2) + } + 1 => { + recog.precpred(None, 1) + } + _ => true + } + } +} +//------------------- prog ---------------- +pub type ProgContextAll<'input, 'arena, Tok = CommonToken<'input>> = ProgContext<'input, 'arena, Tok>; + +pub type ProgContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ProgContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ProgContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ProgContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ProgContext } + fn get_rule_index(&self) -> usize { RULE_prog } + fn make_node( + arena: &'arena Arena, + ctx: ProgContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ProgContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ProgContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ProgContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ProgContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ProgContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ProgContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ProgContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + fn stmt_all(&self) -> Vec<&'arena StmtContextAll<'input, 'arena, Tok>>; + fn stmt(&self, i: usize) -> Option<&'arena StmtContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> ProgContextAttrs<'input, 'arena, Tok> for ProgContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == GuardExpr_EOF) + } + fn stmt_all(&self) -> Vec<&'arena StmtContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn stmt(&self, i: usize) -> Option<&'arena StmtContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn prog(&mut self,) -> Result<&'arena ProgContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(ProgContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_prog)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ProgContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(11); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { + { + { + /*InvokeRule stmt*/ + recog.base.set_state(10); + recog.stmt()?; + } + } + recog.base.set_state(13); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !((((_la) & !0x3f) == 0 && ((1usize << _la) & 13330) != 0)) {break} + } + recog.base.set_state(15); + recog.base.match_token(GuardExpr_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- stmt ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum StmtContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + EvalContext(EvalContext<'input, 'arena, Tok>), + AssignContext(AssignContext<'input, 'arena, Tok>), + Error(StmtContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { StmtContextAll { } { EvalContext, AssignContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { StmtContextAll { } { EvalContext, AssignContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { GuardExprParserNodeKind::StmtContextAll { EvalContext, AssignContext, Error, } } +dbt_antlr4::impl_node_inner! { GuardExprParserNodeKind::StmtContext::StmtContextAll { EvalContext, AssignContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { GuardExprListener::GuardExprParserNodeKind::StmtContextAll { EvalContext(enter_eval, exit_eval), AssignContext(enter_assign, exit_assign), } } + +impl<'input, 'arena, Tok> Deref for StmtContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn StmtContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use StmtContextAll::*; + match self{ + EvalContext(inner) => inner, + AssignContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type StmtContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, StmtContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct StmtContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for StmtContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } + fn get_rule_index(&self) -> usize { RULE_stmt } + fn make_node( + arena: &'arena Arena, + ctx: StmtContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StmtContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a StmtContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => StmtContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut StmtContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut StmtContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> StmtContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, StmtContextExt { + ph: PhantomData + } + ) + } +} + +pub trait StmtContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> StmtContextAttrs<'input, 'arena, Tok> for StmtContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type EvalContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EvalContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait EvalContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EvalContextAttrs<'input, 'arena, Tok> for EvalContext<'input, 'arena, Tok> +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct EvalContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: StmtContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for EvalContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } + fn get_rule_index(&self) -> usize { RULE_stmt } + fn make_node( + arena: &'arena Arena, + ctx: EvalContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StmtContextAll::EvalContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a EvalContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => StmtContextAll<'input, 'arena, Tok>) { + StmtContextAll::EvalContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut EvalContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut StmtContextAll<'input, 'arena, Tok>) { + StmtContextAll::EvalContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> StmtContextAttrs<'input, 'arena, Tok> for EvalContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EvalContextExt<'input, 'arena, Tok> { + fn new(base: StmtContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut StmtContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + StmtContextAll::EvalContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type AssignContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AssignContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait AssignContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>>; + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AssignContextAttrs<'input, 'arena, Tok> for AssignContext<'input, 'arena, Tok> +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AssignContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: StmtContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AssignContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } + fn get_rule_index(&self) -> usize { RULE_stmt } + fn make_node( + arena: &'arena Arena, + ctx: AssignContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StmtContextAll::AssignContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AssignContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => StmtContextAll<'input, 'arena, Tok>) { + StmtContextAll::AssignContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AssignContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut StmtContextAll<'input, 'arena, Tok>) { + StmtContextAll::AssignContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> StmtContextAttrs<'input, 'arena, Tok> for AssignContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AssignContextExt<'input, 'arena, Tok> { + fn new(base: StmtContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut StmtContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + StmtContextAll::AssignContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn stmt(&mut self,) -> Result<&'arena StmtContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(StmtContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_stmt)?; + let _local_ctx_fn = |recog: &Self| -> &'arena StmtContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(26); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__0 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + AssignContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena AssignContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(17); + recog.base.match_token(GuardExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(18); + recog.expr_rec(0)?; + recog.base.set_state(19); + recog.base.match_token(GuardExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(20); + recog.expr_rec(0)?; + recog.base.set_state(21); + recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; + }} + GuardExpr_T__3 |GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + EvalContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena EvalContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + /*InvokeRule expr*/ + recog.base.set_state(23); + recog.expr_rec(0)?; + recog.base.set_state(24); + recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- expr ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum ExprContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + NotContext(NotContext<'input, 'arena, Tok>), + PredicatedContext(PredicatedContext<'input, 'arena, Tok>), + OrContext(OrContext<'input, 'arena, Tok>), + AndContext(AndContext<'input, 'arena, Tok>), + Error(ExprContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { ExprContextAll { } { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { ExprContextAll { } { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { GuardExprParserNodeKind::ExprContextAll { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_node_inner! { GuardExprParserNodeKind::ExprContext::ExprContextAll { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { GuardExprListener::GuardExprParserNodeKind::ExprContextAll { NotContext(enter_not, exit_not), PredicatedContext(enter_predicated, exit_predicated), OrContext(enter_or, exit_or), AndContext(enter_and, exit_and), } } + +impl<'input, 'arena, Tok> Deref for ExprContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn ExprContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use ExprContextAll::*; + match self{ + NotContext(inner) => inner, + PredicatedContext(inner) => inner, + OrContext(inner) => inner, + AndContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type ExprContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ExprContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ExprContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ExprContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: ExprContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ExprContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ExprContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ExprContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ExprContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ExprContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ExprContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> ExprContextAttrs<'input, 'arena, Tok> for ExprContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type NotContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NotContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait NotContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct NotContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NotContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: NotContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::NotContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NotContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::NotContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NotContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::NotContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::NotContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type PredicatedContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PredicatedContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait PredicatedContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn value(&self) -> Option<&'arena ValueContextAll<'input, 'arena, Tok>>; + fn pred(&self) -> Option<&'arena PredContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> +{ + fn value(&self) -> Option<&'arena ValueContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + fn pred(&self) -> Option<&'arena PredContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct PredicatedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PredicatedContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: PredicatedContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::PredicatedContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PredicatedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::PredicatedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PredicatedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::PredicatedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::PredicatedContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type OrContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, OrContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait OrContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>>; + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct OrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for OrContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: OrContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::OrContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a OrContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::OrContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut OrContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::OrContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::OrContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type AndContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AndContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait AndContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>>; + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AndContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AndContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: AndContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::AndContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AndContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::AndContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AndContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::AndContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::AndContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn expr(&mut self,) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.expr_rec(0) + } + + fn expr_rec(&mut self, _p: i32) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_expr, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ExprContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 4; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(35); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { + { + recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + /*InvokeRule value*/ + recog.base.set_state(29); + recog.value()?; + recog.base.set_state(31); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + x if x == 1=>{ + { + /*InvokeRule pred*/ + recog.base.set_state(30); + recog.pred()?; + } + } + + _ => {} + } + }} + GuardExpr_T__3 => { + { + recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(33); + recog.base.match_token(GuardExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(34); + recog.expr_rec(3)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(45); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(5,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(4,&mut recog.base)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AndContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(37); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(38); + recog.base.match_token(GuardExpr_T__4,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(39); + recog.expr_rec(3)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + OrContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(40); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(41); + recog.base.match_token(GuardExpr_T__5,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(42); + recog.expr_rec(2)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(47); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(5,&mut recog.base)?; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- pred ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum PredContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + CmpContext(CmpContext<'input, 'arena, Tok>), + InListContext(InListContext<'input, 'arena, Tok>), + Error(PredContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { PredContextAll { } { CmpContext, InListContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { PredContextAll { } { CmpContext, InListContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { GuardExprParserNodeKind::PredContextAll { CmpContext, InListContext, Error, } } +dbt_antlr4::impl_node_inner! { GuardExprParserNodeKind::PredContext::PredContextAll { CmpContext, InListContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { GuardExprListener::GuardExprParserNodeKind::PredContextAll { CmpContext(enter_cmp, exit_cmp), InListContext(enter_inList, exit_inList), } } + +impl<'input, 'arena, Tok> Deref for PredContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn PredContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use PredContextAll::*; + match self{ + CmpContext(inner) => inner, + InListContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type PredContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PredContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct PredContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PredContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: PredContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PredContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PredContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PredContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PredContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, PredContextExt { + ph: PhantomData + } + ) + } +} + +pub trait PredContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> PredContextAttrs<'input, 'arena, Tok> for PredContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type CmpContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, CmpContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait CmpContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn value(&self) -> Option<&'arena ValueContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> +{ + fn value(&self) -> Option<&'arena ValueContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct CmpContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: PredContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CmpContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: CmpContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::CmpContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a CmpContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { + PredContextAll::CmpContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut CmpContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { + PredContextAll::CmpContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextExt<'input, 'arena, Tok> { + fn new(base: PredContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut PredContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + PredContextAll::CmpContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type InListContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, InListContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait InListContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> InListContextAttrs<'input, 'arena, Tok> for InListContext<'input, 'arena, Tok> +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct InListContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: PredContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for InListContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: InListContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::InListContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a InListContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { + PredContextAll::InListContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut InListContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { + PredContextAll::InListContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for InListContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> InListContextExt<'input, 'arena, Tok> { + fn new(base: PredContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut PredContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + PredContextAll::InListContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn pred(&mut self,) -> Result<&'arena PredContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_pred)?; + let _local_ctx_fn = |recog: &Self| -> &'arena PredContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(55); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__1 |GuardExpr_T__6 |GuardExpr_T__7 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + CmpContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(48); + _la = recog.base.input.la(1); + if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 388) != 0)) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule value*/ + recog.base.set_state(49); + recog.value()?; + }} + GuardExpr_T__8 => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + InListContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena InListContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(50); + recog.base.match_token(GuardExpr_T__8,&mut recog.err_handler)?; + recog.base.set_state(51); + recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(52); + recog.expr_rec(0)?; + recog.base.set_state(53); + recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- value ---------------- +pub type ValueContextAll<'input, 'arena, Tok = CommonToken<'input>> = ValueContext<'input, 'arena, Tok>; + +pub type ValueContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ValueContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ValueContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ValueContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ValueContext } + fn get_rule_index(&self) -> usize { RULE_value } + fn make_node( + arena: &'arena Arena, + ctx: ValueContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ValueContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ValueContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ValueContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ValueContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ValueContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ValueContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ValueContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> ValueContextAttrs<'input, 'arena, Tok> for ValueContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == GuardExpr_ID) + } + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == GuardExpr_INT) + } + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn value(&mut self,) -> Result<&'arena ValueContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(ValueContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_value)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ValueContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(63); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_ID => { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(57); + recog.base.match_token(GuardExpr_ID,&mut recog.err_handler)?; + }} + GuardExpr_INT => { + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(58); + recog.base.match_token(GuardExpr_INT,&mut recog.err_handler)?; + }} + GuardExpr_T__9 => { + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(59); + recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(60); + recog.expr_rec(0)?; + recog.base.set_state(61); + recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 10] = [ + "CAIchAEEAA4ABAIOAgQEDgQEBg4GBAgOCAIACAAYEAAWABgAGgIAAgACAgICAgICAgICAgICAgICAgIG", + "AjYQAgIEAgQCBAYEQBAEAgQCBAYESBAEAgQCBAIEAgQCBAIECgRYEAQUBBgEXhIEAgYCBgIGAgYCBgIG", + "AgYGBnAQBgIIAggCCAIIAggCCAYIgAEQCAIIAAIICgAECAwQAAIEAAQEDhCKAQAWAgAAAAQ0AgAAAAhG", + "AgAAAAxuAgAAABB+AgAAABQYBgQCABYUAgAAABgaAgAAABoWAgAAABocAgAAABweAgAAAB4gCgAAAiAC", + "AgAAACIkCgIAACQmBggEACYoCgQAACgqBggEACosCgYAACw2AgAAAC4wBggEADAyCgYAADI2AgAAADQi", + "AgAAADQuAgAAADYGAgAAADg6DAQBADo+BhAIADxABgwGAD48AgAAAD5AAgAAAEBIAgAAAEJECggAAERI", + "BggEBkY4AgAAAEZCAgAAAEhaAgAAAEpMFAQAAExOCgoAAE5YBggEBlBSFAIAAFJUCgwAAFRYBggEBFZK", + "AgAAAFZQAgAAAFheAgAAAFpWAgAAAFpcAgAAAFwKAgAAAF5aAgAAAGBiDgAAAGJwBhAIAGRmChIAAGZo", + "ChQAAGhqBggEAGpsChYAAGxwAgAAAG5gAgAAAG5kAgAAAHAOAgAAAHKAAQoYAAB0gAEKGgAAdngKFAAA", + "eHoGCAQAenwKFgAAfIABAgAAAH5yAgAAAH50AgAAAH52AgAAAIABEgIAAAAQGjQ+RlZabn4=" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index 698cf57c0c..12fa46c520 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -1697,12 +1697,12 @@ static _serializedATN: [&'static str; 19] = [ "FAYAAGJkDgIAAGRuBgwGCGZoFAQAAGhqDgQAAGpuBgwGBmxgAgAAAGxmAgAAAG50AgAAAHBsAgAAAHBy", "AgAAAHIOAgAAAHRwAgAAAHaKAQoeAAB4igEKIAAAenwKGAAAfH4GBAIAfoABChoAAIABigECAAAAggGE", "AQoeAACEAYYBChwAAIYBigEGBAIAiAF2AgAAAIgBeAIAAACIAXoCAAAAiAGCAQIAAACKARICAAAAEiAo", - "ODxEVmxwiAEMEhIAEjAABAIEBAICBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", - "EBYOGhoQAAQGDAACBAAAAAAMDAwEBAIGBgQADAYMAAIEAAAAAAwMDBASAhQWBAAQGkgABgAEAgICAgIC", - "AgIIAAACAAAAAAAAAAAAAAASEkhISEhISEhISEhIGBgCHh4EICAGAQEIAgIKBAQMBgYOCAgQCg4SEBYU", - "GhoWHBwYAAESMAAEBAECBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4a", - "GhAAARIwAAQEAQQEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAAB", - "AgAEAAAAAAESMAAEBAQEBAQCBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4a", - "GhAAARQ2AAQEBAQEBAIEBAQAAAAAAAAAAAAANjY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBASDhQW", - "EBoaEgAEBgQCBAgKDA4EBAYOEAw=" + "ODxEVmxwiAEOEhIAEjAABAIEBAICBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", + "EBYOGhoQAAAAAAQGDAACBAAAAAAMDAwEBAIGBgQAAAAADAYMAAIEAAAAAAwMDBASAhQWBAAAAAAQGkgA", + "BgAEAgICAgICAgIIAAACAAAAAAAAAAAAAAASEkhISEhISEhISEhIGBgCHh4EICAGAQEIAgIKBAQMBgYO", + "CAgQCg4SEBYUGhoWHBwYAAAAAAESMAAEBAECBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYG", + "BggICAoKDgwQFg4aGhAAAAAAARIwAAQEAQQEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYG", + "CAgICgoODBAWDhoaEAAAAAABAgAEAAAAAAAAAAESMAAEBAQEBAQCBAQAAAAAAAAAAAAwMDAwMDAwMDAB", + "AQICAgQEBAYGBggICAoKDgwQFg4aGhAAAAAAARQ2AAQEBAQEBAIEBAQAAAAAAAAAAAAANjY2NjY2NjY2", + "NgEBAgICBAQEBgYGCAgICgoODBASDhQWEBoaEgAAAAAEBgQCBAgKDA4EBAYOEAw=" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index 35ad91cb21..af88a052d0 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -1265,20 +1265,20 @@ static _serializedATN: [&'static str; 30] = [ "hgGuAQYMBgCIAa4BCh4AAIoBjAEKGAAAjAGOAQYQCACOAZABChoAAJABrgECAAAAkgGUAQocAACUAaYB", "ChgAAJYBoAEGEAgAmAGaAQoCAACaAZ4BBhAIAJwBmAECAAAAngGkAQIAAACgAZwBAgAAAKABogECAAAA", "ogGoAQIAAACkAaABAgAAAKYBlgECAAAApgGoAQIAAACoAaoBAgAAAKoBrgEKGgAArAGGAQIAAACsAYgB", - "AgAAAKwBigECAAAArAGSAQIAAACuARYCAAAAFCIqPE5cfIABoAGmAawBDBIUBEDOAwAAAAAAAAQEBAIA", + "AgAAAKwBigECAAAArAGSAQIAAACuARYCAAAAFCIqPE5cfIABoAGmAawBDhIUBEDOAwAAAAAAAAQEBAIA", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQEAAAAAAAAAAAAAAAAAAQAAAQEAAAAAAAAAAAAHkhISHic", "AZwBnAGcAZwBqAHGAeQB5AH8AfwB/AGaAqwC4gLiAuICngPOA84DzgPOA84DzgPOA84DzgMGBgIODgQY", "GAYcHAgeHgoBAQwCAg4EBBAGBhIICBQKChYOFhgBAQwCAg4EBBAGBhIICBQKChYOFhgYGBoBAQwCAg4E", "BBAGBhIKChYOFhgGBgIcHAIGBhwODh4YGCAcHCIeHiQGBiYODigYGCocHCweHi4ICDAKCjIMDAoOFjQI", "CDAKCjIMDAoOFjQYGDYKCjIMDAoOFjQBAQwCAg4EBBAGBhIICDgKCjoODhgQFDwWFhgBAQwCAg4EBBAG", "BhIICDgKCjoODhgQFDwWFhgYGD4BAQwCAg4EBBAGBhIKCjoODhgQFDwWFhgeBAQCBAYEAgQaBAIEHgQC", - "BCAEAgQoBAIEKgQCBDAEAgQyBAIENAQCBDYEAgQ4BAIEOgQCBDwEAgQ+BAIEBhQ2AAQEBAQCBAQEBAQA", - "AAAAAAAAAAAANjY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoKDAwMDg4WEBoaEgAKCh4ACAYCBAAAAAAA", - "AB4eHh4eCgoCDg4EEBAGEhQIFhYEABIeVAACBgAEAgICAgICAgIIAgAAAAIAAAAAAAAAAAAAAAAYGBhU", - "VFRUVFRUVFRUVFQGBgIYGAQcHAYeHggBAQoCAgwEBA4GBhAICBIKChQMDBYOFhgYGBoaGhwAARIwAAQE", - "BAQCBAIEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAoKCgwMDA4WDhoaEAABFDwABAQEBAIE", - "BAIEBAAAAAAAAAAAAAA8PDw8PDw8PDw8AQECAgIEBAQGBgYICgoKDAwMDg4OEBQQFhYOGhoSAAEUPAAE", - "BAQEAgQEAgQEAAAAAAAAAAAAADw8PDw8PDw8PDwBAQICAgQEBAYGBggKCgoMDAwODg4QEBASFg4aGhIA", - "ARIwAAQEBAQCBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAoKCgwMDA4WDhoaEAABAgAE", - "AAAAAAIMCAQGCAwICgwOEA==" + "BCAEAgQoBAIEKgQCBDAEAgQyBAIENAQCBDYEAgQ4BAIEOgQCBDwEAgQ+BAIEAAAABhQ2AAQEBAQCBAQE", + "BAQAAAAAAAAAAAAANjY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoKDAwMDg4WEBoaEgAAAAAKCh4ACAYC", + "BAAAAAAAAB4eHh4eCgoCDg4EEBAGEhQIFhYEAAAAABIeVAACBgAEAgICAgICAgIIAgAAAAIAAAAAAAAA", + "AAAAAAAYGBhUVFRUVFRUVFRUVFQGBgIYGAQcHAYeHggBAQoCAgwEBA4GBhAICBIKChQMDBYOFhgYGBoa", + "GhwAAAAAARIwAAQEBAQCBAIEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYGCAoKCgwMDA4WDhoa", + "EAAAAAABFDwABAQEBAIEBAIEBAAAAAAAAAAAAAA8PDw8PDw8PDw8AQECAgIEBAQGBgYICgoKDAwMDg4O", + "EBQQFhYOGhoSAAAAAAEUPAAEBAQEAgQEAgQEAAAAAAAAAAAAADw8PDw8PDw8PDwBAQICAgQEBAYGBggK", + "CgoMDAwODg4QEBASFg4aGhIAAAAAARIwAAQEBAQCBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQE", + "BgYGCAoKCgwMDA4WDhoaEAAAAAABAgAEAAAAAAAAAAIMCAQGCAwICgwOEA==" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/guardexprbaselistener.rs b/runtime/Rust/tests/gen/guardexprbaselistener.rs new file mode 100644 index 0000000000..edf77eaf17 --- /dev/null +++ b/runtime/Rust/tests/gen/guardexprbaselistener.rs @@ -0,0 +1,131 @@ +// Generated from GuardExpr.g4 by ANTLR 4.13.2 + +use super::guardexprparser::*; +use dbt_antlr4::tree::ParseTreeListener; + +// A complete Visitor for a parse tree produced by GuardExprParser. + +pub trait GuardExprBaseListener<'arena>: + ParseTreeListener<'arena, GuardExprParserNodeKind> { + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_prog(&mut self, _ctx: &ProgContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_prog(&mut self, _ctx: &ProgContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_assign(&mut self, _ctx: &AssignContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_assign(&mut self, _ctx: &AssignContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_eval(&mut self, _ctx: &EvalContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_eval(&mut self, _ctx: &EvalContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_not(&mut self, _ctx: &NotContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_not(&mut self, _ctx: &NotContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_predicated(&mut self, _ctx: &PredicatedContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_predicated(&mut self, _ctx: &PredicatedContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_or(&mut self, _ctx: &OrContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_or(&mut self, _ctx: &OrContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_and(&mut self, _ctx: &AndContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_and(&mut self, _ctx: &AndContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_cmp(&mut self, _ctx: &CmpContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_cmp(&mut self, _ctx: &CmpContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_inlist(&mut self, _ctx: &InListContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_inlist(&mut self, _ctx: &InListContext<'input, 'arena>) {} + + + /** + * Enter a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree +, */ + fn enter_value(&mut self, _ctx: &ValueContext<'input, 'arena>) {} + /** + * Exit a parse tree produced by \{@link GuardExprBaseParser#s}. + * @param ctx the parse tree + */ + fn exit_value(&mut self, _ctx: &ValueContext<'input, 'arena>) {} + + +} \ No newline at end of file diff --git a/runtime/Rust/tests/gen/guardexprlexer.rs b/runtime/Rust/tests/gen/guardexprlexer.rs new file mode 100644 index 0000000000..31533c85cb --- /dev/null +++ b/runtime/Rust/tests/gen/guardexprlexer.rs @@ -0,0 +1,142 @@ +// Generated from GuardExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(nonstandard_style)] +#![allow(unused_variables)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::atn::ATN; +use dbt_antlr4::char_stream::CharStream; +use dbt_antlr4::int_stream::IntStream; +use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; +use dbt_antlr4::atn_config_set::LexerATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::TokenSource; +use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::recognizer::Actions; +use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; +use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; + +use std::ops::{DerefMut, Deref}; +use std::sync::LazyLock; + +dbt_antlr4::check_version!("2","0"); +pub const T__0:i32=1; +pub const T__1:i32=2; +pub const T__2:i32=3; +pub const T__3:i32=4; +pub const T__4:i32=5; +pub const T__5:i32=6; +pub const T__6:i32=7; +pub const T__7:i32=8; +pub const T__8:i32=9; +pub const T__9:i32=10; +pub const T__10:i32=11; +pub const ID:i32=12; +pub const INT:i32=13; +pub const WS:i32=14; + +pub const channelNames: [&'static str;0+2] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" +]; + +pub const modeNames: [&'static str;1] = [ + "DEFAULT_MODE" +]; + +pub const ruleNames: [&'static str;14] = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "ID", "INT", "WS" +]; +pub const _LITERAL_NAMES: [Option<&'static str>;12] = [ + None, Some("'set'"), Some("'='"), Some("';'"), Some("'NOT'"), Some("'AND'"), + Some("'OR'"), Some("'<'"), Some("'>'"), Some("'IN'"), Some("'('"), Some("')'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;15] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type LexerContext<'input, 'arena> = BaseRuleContext<'input, 'arena, EmptyNodeKind, EmptyCustomRuleContext<'input, 'arena>>; +pub type BaseLexerType<'input, 'arena, Input, TF> = BaseLexer<'input, 'arena, GuardExprLexerActions, Input, TF>; +pub fn lexer_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct GuardExprLexer<'input, 'arena, Input, TF = CommonTokenFactory<'input, 'arena>> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + base: BaseLexerType<'input, 'arena, Input, TF>, +} + +dbt_antlr4::impl_token_source! { GuardExprLexer } +dbt_antlr4::impl_deref! { lexer => GuardExprLexer } + +impl<'input, 'arena, Input, TF> GuardExprLexer<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: CharStream<'input>, +{ + pub fn new(arena: &'arena Arena, input: Input) -> Self { + let actions = GuardExprLexerActions { + }; + let base = BaseLexerType::new_base_lexer(input, actions, arena); + Self { base } + } +} + +pub struct GuardExprLexerActions { +} + +impl GuardExprLexerActions { +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> + for GuardExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, + {} + +impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for GuardExprLexerActions +where + 'input: 'arena, + Input: CharStream<'input>, + TF: TokenFactory<'input, 'arena> + 'arena, +{ + fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } + fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } + fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } + fn get_grammar_file_name(&self) -> &'static str { "GuardExprLexer.g4" } + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 13] = [ + "CAAcmAEMAQQADgAEAg4CBAQOBAQGDgYECA4IBAoOCgQMDgwEDg4OBBAOEAQSDhIEFA4UBBYOFgQYDhgE", + "Gg4aAgACAAIAAgACAgICAgQCBAIGAgYCBgIGAggCCAIIAggCCgIKAgoCDAIMAg4CDgIQAhACEAISAhIC", + "FAIUAhYIFnoQFhYWGBZ8AhgIGIQBEBgWGBgYhgECGggajgEQGhYaGBqQAQIaAhoAABwCAgYECgYOCBIK", + "FgwaDh4QIhImFCoWLhgyGjYcAgAGAgDCAfQBAgBgcgQAEhRAQJwBAAICAAAAAAYCAAAAAAoCAAAAAA4C", + "AAAAABICAAAAABYCAAAAABoCAAAAAB4CAAAAACICAAAAACYCAAAAACoCAAAAAC4CAAAAADICAAAAADYC", + "AAAAAjoCAAAABkICAAAACkYCAAAADkoCAAAAElICAAAAFloCAAAAGmACAAAAHmQCAAAAImgCAAAAJm4C", + "AAAAKnICAAAALngCAAAAMoIBAgAAADaMAQIAAAA6PArmAQAAPD4KygEAAD5ACugBAABABAIAAABCRAp6", + "AABECAIAAABGSAp2AABIDAIAAABKTAqcAQAATE4KngEAAE5QCqgBAABQEAIAAABSVAqCAQAAVFYKnAEA", + "AFZYCogBAABYFAIAAABaXAqeAQAAXF4KpAEAAF4YAgAAAGBiCngAAGIcAgAAAGRmCnwAAGYgAgAAAGhq", + "CpIBAABqbAqcAQAAbCQCAAAAbnAKUAAAcCgCAAAAcnQKUgAAdCwCAAAAdnoOAAAAeHYCAAAAenwCAAAA", + "fHgCAAAAfH4CAAAAfjACAAAAgAGEAQ4CAACCAYABAgAAAIQBhgECAAAAhgGCAQIAAACGAYgBAgAAAIgB", + "NAIAAACKAY4BDgQAAIwBigECAAAAjgGQAQIAAACQAYwBAgAAAJABkgECAAAAkgGUAQIAAACUAZYBDBoA", + "AJYBOAIAAAAIAHyGAZABAgwAAA==" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/guardexprlistener.rs b/runtime/Rust/tests/gen/guardexprlistener.rs new file mode 100644 index 0000000000..e5226c7745 --- /dev/null +++ b/runtime/Rust/tests/gen/guardexprlistener.rs @@ -0,0 +1,108 @@ +#![allow(nonstandard_style)] +// Generated from GuardExpr.g4 by ANTLR 4.13.2 +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::token::{CommonToken, Token}; +use dbt_antlr4::tree::ParseTreeListener; +use super::guardexprparser::*; + +pub trait GuardExprListener<'arena, Tok = CommonToken<'arena>> : ParseTreeListener<'arena, GuardExprParserNodeKind, Tok> +where + Tok: Token + 'arena, +{ + /// Enter a parse tree produced by {@link GuardExprParser#prog}. + /// @param ctx the parse tree + fn enter_prog<'input: 'arena>(&mut self, _ctx: &ProgContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link GuardExprParser#prog}. + /// @param ctx the parse tree + fn exit_prog<'input: 'arena>(&mut self, _ctx: &ProgContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code assign} + /// labeled alternative in {@link GuardExprParser#stmt}. + /// @param ctx the parse tree + fn enter_assign<'input: 'arena>(&mut self, _ctx: &AssignContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code assign} + /// labeled alternative in {@link GuardExprParser#stmt}. + /// @param ctx the parse tree + fn exit_assign<'input: 'arena>(&mut self, _ctx: &AssignContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code eval} + /// labeled alternative in {@link GuardExprParser#stmt}. + /// @param ctx the parse tree + fn enter_eval<'input: 'arena>(&mut self, _ctx: &EvalContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code eval} + /// labeled alternative in {@link GuardExprParser#stmt}. + /// @param ctx the parse tree + fn exit_eval<'input: 'arena>(&mut self, _ctx: &EvalContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code not} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn enter_not<'input: 'arena>(&mut self, _ctx: &NotContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code not} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn exit_not<'input: 'arena>(&mut self, _ctx: &NotContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code predicated} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn enter_predicated<'input: 'arena>(&mut self, _ctx: &PredicatedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code predicated} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn exit_predicated<'input: 'arena>(&mut self, _ctx: &PredicatedContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code or} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn enter_or<'input: 'arena>(&mut self, _ctx: &OrContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code or} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn exit_or<'input: 'arena>(&mut self, _ctx: &OrContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code and} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn enter_and<'input: 'arena>(&mut self, _ctx: &AndContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code and} + /// labeled alternative in {@link GuardExprParser#expr}. + /// @param ctx the parse tree + fn exit_and<'input: 'arena>(&mut self, _ctx: &AndContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code cmp} + /// labeled alternative in {@link GuardExprParser#pred}. + /// @param ctx the parse tree + fn enter_cmp<'input: 'arena>(&mut self, _ctx: &CmpContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code cmp} + /// labeled alternative in {@link GuardExprParser#pred}. + /// @param ctx the parse tree + fn exit_cmp<'input: 'arena>(&mut self, _ctx: &CmpContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by the {@code inList} + /// labeled alternative in {@link GuardExprParser#pred}. + /// @param ctx the parse tree + fn enter_inList<'input: 'arena>(&mut self, _ctx: &InListContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by the {@code inList} + /// labeled alternative in {@link GuardExprParser#pred}. + /// @param ctx the parse tree + fn exit_inList<'input: 'arena>(&mut self, _ctx: &InListContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Enter a parse tree produced by {@link GuardExprParser#value}. + /// @param ctx the parse tree + fn enter_value<'input: 'arena>(&mut self, _ctx: &ValueContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + + /// Exit a parse tree produced by {@link GuardExprParser#value}. + /// @param ctx the parse tree + fn exit_value<'input: 'arena>(&mut self, _ctx: &ValueContext<'input, 'arena, Tok>) -> Result<(), ANTLRError> { Ok(()) } + +} diff --git a/runtime/Rust/tests/gen/guardexprparser.rs b/runtime/Rust/tests/gen/guardexprparser.rs new file mode 100644 index 0000000000..fa56ce7e74 --- /dev/null +++ b/runtime/Rust/tests/gen/guardexprparser.rs @@ -0,0 +1,1820 @@ +// Generated from GuardExpr.g4 by ANTLR 4.13.2 +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(nonstandard_style)] +#![allow(unused_braces)] +#![allow(unused_parens)] +use dbt_antlr4::Arena; +use dbt_antlr4::PredictionContextCache; +use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; +use dbt_antlr4::token::CommonToken; +use dbt_antlr4::token_stream::TokenStream; +use dbt_antlr4::TokenSource; +use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; +use dbt_antlr4::errors::ANTLRError; +use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; +use dbt_antlr4::recognizer::{Recognizer,Actions}; +use dbt_antlr4::atn_config_set::ATNConfigSet; +use dbt_antlr4::atn_deserializer::ATNDeserializer; +use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; +use dbt_antlr4::atn::{ATN, INVALID_ALT}; +use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; +use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +use dbt_antlr4::tree::*; +use dbt_antlr4::token::{TOKEN_EOF,Token}; +use dbt_antlr4::int_stream::EOF; +use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; +use dbt_antlr4::token_factory::TokenFactory; +use super::guardexprlistener::*; +use std::marker::PhantomData; +use std::sync::LazyLock; +use std::rc::Rc; +use std::ops::{DerefMut, Deref}; + +dbt_antlr4::check_version!("2","0"); +pub const GuardExpr_T__0:i32=1; +pub const GuardExpr_T__1:i32=2; +pub const GuardExpr_T__2:i32=3; +pub const GuardExpr_T__3:i32=4; +pub const GuardExpr_T__4:i32=5; +pub const GuardExpr_T__5:i32=6; +pub const GuardExpr_T__6:i32=7; +pub const GuardExpr_T__7:i32=8; +pub const GuardExpr_T__8:i32=9; +pub const GuardExpr_T__9:i32=10; +pub const GuardExpr_T__10:i32=11; +pub const GuardExpr_ID:i32=12; +pub const GuardExpr_INT:i32=13; +pub const GuardExpr_WS:i32=14; +pub const GuardExpr_EOF:i32=EOF; +pub const RULE_prog:usize = 0; +pub const RULE_stmt:usize = 1; +pub const RULE_expr:usize = 2; +pub const RULE_pred:usize = 3; +pub const RULE_value:usize = 4; +pub const ruleNames: [&'static str; 5] = [ + "prog", "stmt", "expr", "pred", "value" +]; + +pub const _LITERAL_NAMES: [Option<&'static str>;12] = [ + None, Some("'set'"), Some("'='"), Some("';'"), Some("'NOT'"), Some("'AND'"), + Some("'OR'"), Some("'<'"), Some("'>'"), Some("'IN'"), Some("'('"), Some("')'") +]; +pub const _SYMBOLIC_NAMES: [Option<&'static str>;15] = [ + None, None, None, None, None, None, None, None, None, None, None, None, + Some("ID"), Some("INT"), Some("WS") +]; + +static VOCABULARY: LazyLock> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); + +pub type BaseParserType<'input, 'arena, Input, TF> = BaseParser<'input, 'arena, GuardExprParserExt<'input, 'arena>, GuardExprParserNodeKind, Input, TF>; +pub fn parser_simulator_manager() -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } + +pub struct GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + base: BaseParserType<'input, 'arena, Input, TF>, + err_handler: ErrorStrategyDelegate<'input, 'arena, TF, BaseParserType<'input, 'arena, Input, TF>>, +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn with_strategy(arena: &'arena Arena, input: Input, strategy: Box> + 'arena>) -> Self { + Self { + base: BaseParser::new_base_parser( + arena, input, + GuardExprParserExt { + _pd: Default::default(), + } + ), + err_handler: unsafe { ErrorStrategyDelegate::new(strategy) }, + } + } + + pub fn new(arena: &'arena Arena, input: Input) -> Self{ + Self::with_strategy(arena, input, Box::new(DefaultErrorStrategy::new())) + } + + pub fn set_error_strategy(&mut self, strategy: Box> + 'arena>) { + self.err_handler = unsafe { ErrorStrategyDelegate::new(strategy) }; + } + + /// Adds parse listener for this parser + /// returns `listener_id` that can be used later to get listener back + /// + /// ### Example for listener usage: + /// todo + pub fn add_parse_listener( + &mut self, + listener: Box, + ) -> ListenerId + where + L: GuardExprListener<'arena, TF::Tok> + 'static, + { + let id = ListenerId::new(&listener); + self.base.add_dyn_parse_listener(listener); + id + } +} +pub struct GuardExprTreeWalker; +impl GuardExprTreeWalker +{ + pub fn walk<'input, 'arena, Tok, L, T>( + listener: Box, + tree: &'arena T, + ) -> Result, ANTLRError> + where + 'input: 'arena, + L: GuardExprListener<'arena, Tok> + 'static, + T: NodeInner<'input, 'arena, GuardExprParserNodeKind, Tok>, + Tok: Token + 'input, + { + let listener_ptr = Box::into_raw(listener); + let listener = unsafe { Box::from_raw(listener_ptr as *mut >::Listener) }; + let listener = ParseTreeWalker::walk(listener, tree.as_node())?; + Ok(unsafe { Box::from_raw(Box::into_raw(listener) as *mut L) } ) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u16)] +pub enum GuardExprParserNodeKind { + ProgContext, + StmtContext, + ExprContext, + PredContext, + ValueContext, + Terminal, + Error, +} +pub type GuardExprParserNode<'input, 'arena, Tok = CommonToken<'input>> = TreeNode<'input, 'arena, GuardExprParserNodeKind, Tok>; + +dbt_antlr4::impl_deref! { parser => GuardExprParser } +dbt_antlr4::impl_node_kind! { GuardExprParserNodeKind { + StmtContext(StmtContextAll), ExprContext(ExprContextAll), PredContext(PredContextAll), ; ProgContext(enter_prog, exit_prog, ), ValueContext(enter_value, exit_value, ), + }; listener = dyn GuardExprListener<'arena, Tok>, +} + +pub struct GuardExprParserExt<'input, 'arena> { + _pd: PhantomData<(&'input str, &'arena ())>, +} + +impl<'input, 'arena> GuardExprParserExt<'input, 'arena> { +} + +impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for GuardExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena { + fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } +} + +impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for GuardExprParserExt<'input, 'arena> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn get_grammar_file_name(&self) -> & str{ "GuardExpr.g4" } + fn get_rule_names(&self) -> &[& str] { &ruleNames } + fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } + fn sempred(_localctx: Option<&'arena GuardExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, + recog:&mut BaseParserType<'input, 'arena, Input, TF> + ) -> bool { + match rule_index { + 2 => GuardExprParser::<'input, 'arena, Input, TF>::expr_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), + _ => true + } + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + fn expr_sempred(_ctx: Option<&'arena ExprContext<'input, 'arena, TF::Tok>>, pred_index:i32, recog: &mut ::Target) -> bool + { + match pred_index { + 0 => { + recog.precpred(None, 2) + } + 1 => { + recog.precpred(None, 1) + } + _ => true + } + } +} +//------------------- prog ---------------- +pub type ProgContextAll<'input, 'arena, Tok = CommonToken<'input>> = ProgContext<'input, 'arena, Tok>; + +pub type ProgContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ProgContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ProgContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ProgContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ProgContext } + fn get_rule_index(&self) -> usize { RULE_prog } + fn make_node( + arena: &'arena Arena, + ctx: ProgContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ProgContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ProgContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ProgContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ProgContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ProgContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ProgContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ProgContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + fn stmt_all(&self) -> Vec<&'arena StmtContextAll<'input, 'arena, Tok>>; + fn stmt(&self, i: usize) -> Option<&'arena StmtContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> ProgContextAttrs<'input, 'arena, Tok> for ProgContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves first TerminalNode corresponding to token EOF + /// Returns `None` if there is no child corresponding to token EOF + fn EOF(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == GuardExpr_EOF) + } + fn stmt_all(&self) -> Vec<&'arena StmtContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn stmt(&self, i: usize) -> Option<&'arena StmtContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn prog(&mut self,) -> Result<&'arena ProgContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(ProgContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_prog)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ProgContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(11); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { + { + { + /*InvokeRule stmt*/ + recog.base.set_state(10); + recog.stmt()?; + } + } + recog.base.set_state(13); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !((((_la) & !0x3f) == 0 && ((1usize << _la) & 13330) != 0)) {break} + } + recog.base.set_state(15); + recog.base.match_token(GuardExpr_EOF,&mut recog.err_handler)?; + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- stmt ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum StmtContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + EvalContext(EvalContext<'input, 'arena, Tok>), + AssignContext(AssignContext<'input, 'arena, Tok>), + Error(StmtContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { StmtContextAll { } { EvalContext, AssignContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { StmtContextAll { } { EvalContext, AssignContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { GuardExprParserNodeKind::StmtContextAll { EvalContext, AssignContext, Error, } } +dbt_antlr4::impl_node_inner! { GuardExprParserNodeKind::StmtContext::StmtContextAll { EvalContext, AssignContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { GuardExprListener::GuardExprParserNodeKind::StmtContextAll { EvalContext(enter_eval, exit_eval), AssignContext(enter_assign, exit_assign), } } + +impl<'input, 'arena, Tok> Deref for StmtContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn StmtContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use StmtContextAll::*; + match self{ + EvalContext(inner) => inner, + AssignContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type StmtContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, StmtContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct StmtContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for StmtContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } + fn get_rule_index(&self) -> usize { RULE_stmt } + fn make_node( + arena: &'arena Arena, + ctx: StmtContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StmtContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a StmtContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => StmtContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut StmtContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut StmtContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> StmtContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, StmtContextExt { + ph: PhantomData + } + ) + } +} + +pub trait StmtContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> StmtContextAttrs<'input, 'arena, Tok> for StmtContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type EvalContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EvalContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait EvalContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EvalContextAttrs<'input, 'arena, Tok> for EvalContext<'input, 'arena, Tok> +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct EvalContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: StmtContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for EvalContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } + fn get_rule_index(&self) -> usize { RULE_stmt } + fn make_node( + arena: &'arena Arena, + ctx: EvalContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StmtContextAll::EvalContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a EvalContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => StmtContextAll<'input, 'arena, Tok>) { + StmtContextAll::EvalContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut EvalContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut StmtContextAll<'input, 'arena, Tok>) { + StmtContextAll::EvalContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> StmtContextAttrs<'input, 'arena, Tok> for EvalContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> EvalContextExt<'input, 'arena, Tok> { + fn new(base: StmtContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut StmtContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + StmtContextAll::EvalContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type AssignContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AssignContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait AssignContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>>; + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AssignContextAttrs<'input, 'arena, Tok> for AssignContext<'input, 'arena, Tok> +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AssignContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: StmtContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AssignContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } + fn get_rule_index(&self) -> usize { RULE_stmt } + fn make_node( + arena: &'arena Arena, + ctx: AssignContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(StmtContextAll::AssignContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AssignContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => StmtContextAll<'input, 'arena, Tok>) { + StmtContextAll::AssignContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AssignContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut StmtContextAll<'input, 'arena, Tok>) { + StmtContextAll::AssignContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> StmtContextAttrs<'input, 'arena, Tok> for AssignContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AssignContextExt<'input, 'arena, Tok> { + fn new(base: StmtContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut StmtContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + StmtContextAll::AssignContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn stmt(&mut self,) -> Result<&'arena StmtContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(StmtContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_stmt)?; + let _local_ctx_fn = |recog: &Self| -> &'arena StmtContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(26); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__0 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + AssignContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena AssignContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(17); + recog.base.match_token(GuardExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(18); + recog.expr_rec(0)?; + recog.base.set_state(19); + recog.base.match_token(GuardExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(20); + recog.expr_rec(0)?; + recog.base.set_state(21); + recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; + }} + GuardExpr_T__3 |GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + EvalContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena EvalContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + /*InvokeRule expr*/ + recog.base.set_state(23); + recog.expr_rec(0)?; + recog.base.set_state(24); + recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- expr ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum ExprContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + NotContext(NotContext<'input, 'arena, Tok>), + PredicatedContext(PredicatedContext<'input, 'arena, Tok>), + OrContext(OrContext<'input, 'arena, Tok>), + AndContext(AndContext<'input, 'arena, Tok>), + Error(ExprContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { ExprContextAll { } { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { ExprContextAll { } { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { GuardExprParserNodeKind::ExprContextAll { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_node_inner! { GuardExprParserNodeKind::ExprContext::ExprContextAll { NotContext, PredicatedContext, OrContext, AndContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { GuardExprListener::GuardExprParserNodeKind::ExprContextAll { NotContext(enter_not, exit_not), PredicatedContext(enter_predicated, exit_predicated), OrContext(enter_or, exit_or), AndContext(enter_and, exit_and), } } + +impl<'input, 'arena, Tok> Deref for ExprContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn ExprContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use ExprContextAll::*; + match self{ + NotContext(inner) => inner, + PredicatedContext(inner) => inner, + OrContext(inner) => inner, + AndContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type ExprContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ExprContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ExprContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ExprContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: ExprContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ExprContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ExprContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ExprContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ExprContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ExprContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ExprContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> ExprContextAttrs<'input, 'arena, Tok> for ExprContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type NotContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NotContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait NotContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct NotContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NotContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: NotContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::NotContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a NotContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::NotContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut NotContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::NotContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::NotContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type PredicatedContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PredicatedContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait PredicatedContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn value(&self) -> Option<&'arena ValueContextAll<'input, 'arena, Tok>>; + fn pred(&self) -> Option<&'arena PredContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> +{ + fn value(&self) -> Option<&'arena ValueContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } + fn pred(&self) -> Option<&'arena PredContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct PredicatedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PredicatedContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: PredicatedContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::PredicatedContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PredicatedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::PredicatedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PredicatedContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::PredicatedContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::PredicatedContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type OrContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, OrContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait OrContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>>; + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct OrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for OrContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: OrContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::OrContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a OrContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::OrContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut OrContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::OrContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::OrContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type AndContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AndContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait AndContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>>; + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> +{ + fn expr_all(&self) -> Vec<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.children_of_type() + } + fn expr(&self, i: usize) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(i) + } +} +#[derive(Debug)] +pub struct AndContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: ExprContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AndContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } + fn get_rule_index(&self) -> usize { RULE_expr } + fn make_node( + arena: &'arena Arena, + ctx: AndContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(ExprContextAll::AndContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a AndContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::AndContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut AndContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { + ExprContextAll::AndContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextExt<'input, 'arena, Tok> { + fn new(base: ExprContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut ExprContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + ExprContextAll::AndContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + #[inline] + pub fn expr(&mut self,) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + self.expr_rec(0) + } + + fn expr_rec(&mut self, _p: i32) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + let _parentState = recog.base.get_state(); + recog.base.enter_recursion_rule(ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_expr, _p)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ExprContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let _startState = 4; + let result: Result<(), ANTLRError> = (|| { + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(35); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { + { + recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + /*InvokeRule value*/ + recog.base.set_state(29); + recog.value()?; + recog.base.set_state(31); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } } { + x if x == 1 =>{ + { + /*InvokeRule pred*/ + recog.base.set_state(30); + recog.pred()?; + } + } + + _ => {} + } + }} + GuardExpr_T__3 => { + { + recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(33); + recog.base.match_token(GuardExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(34); + recog.expr_rec(3)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(45); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(4)?; _sdp } { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AndContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(37); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(38); + recog.base.match_token(GuardExpr_T__4,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(39); + recog.expr_rec(3)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + OrContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(40); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(41); + recog.base.match_token(GuardExpr_T__5,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(42); + recog.expr_rec(2)?; + } + } + + _ => {} + } + } + } + recog.base.set_state(47); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } }; + } + } + Ok(()) + })(); + match result { + Ok(_) => {}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re)=>{ + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?;} + } + recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) + }) + } +} +//------------------- pred ---------------- +#[derive(Debug)] +#[repr(C, u16)] +pub enum PredContextAll<'input, 'arena, Tok = CommonToken<'input>> +where + 'input: 'arena, + Tok: Token + 'input, +{ + CmpContext(CmpContext<'input, 'arena, Tok>), + InListContext(InListContext<'input, 'arena, Tok>), + Error(PredContext<'input, 'arena, Tok>) +} + +dbt_antlr4::impl_rule_context! { PredContextAll { } { CmpContext, InListContext, Error, } } +dbt_antlr4::impl_parser_rule_context! { PredContextAll { } { CmpContext, InListContext, Error, } } +dbt_antlr4::impl_tree_trait_delegates! { GuardExprParserNodeKind::PredContextAll { CmpContext, InListContext, Error, } } +dbt_antlr4::impl_node_inner! { GuardExprParserNodeKind::PredContext::PredContextAll { CmpContext, InListContext, Error, } } +dbt_antlr4::impl_listener_dispatch! { GuardExprListener::GuardExprParserNodeKind::PredContextAll { CmpContext(enter_cmp, exit_cmp), InListContext(enter_inList, exit_inList), } } + +impl<'input, 'arena, Tok> Deref for PredContextAll<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ + type Target = dyn PredContextAttrs<'input, 'arena, Tok> + 'arena; + fn deref(&self) -> &Self::Target{ + use PredContextAll::*; + match self{ + CmpContext(inner) => inner, + InListContext(inner) => inner, + Error(inner) => inner + } + } +} + +pub type PredContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PredContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct PredContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PredContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: PredContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::Error(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a PredContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PredContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut PredContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PredContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, PredContextExt { + ph: PhantomData + } + ) + } +} + +pub trait PredContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input, 'arena, Tok: Token + 'input> PredContextAttrs<'input, 'arena, Tok> for PredContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ +} + +pub type CmpContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, CmpContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait CmpContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn value(&self) -> Option<&'arena ValueContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> +{ + fn value(&self) -> Option<&'arena ValueContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct CmpContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: PredContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CmpContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: CmpContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::CmpContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a CmpContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { + PredContextAll::CmpContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut CmpContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { + PredContextAll::CmpContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextExt<'input, 'arena, Tok> { + fn new(base: PredContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut PredContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + PredContextAll::CmpContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +pub type InListContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, InListContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; + +pub trait InListContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> InListContextAttrs<'input, 'arena, Tok> for InListContext<'input, 'arena, Tok> +{ + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} +#[derive(Debug)] +pub struct InListContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + base: PredContextExt<'input, 'arena, Tok>, + pd: PhantomData<(&'arena (), &'input Tok)> +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for InListContextExt<'input, 'arena, Tok> +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } + fn get_rule_index(&self) -> usize { RULE_pred } + fn make_node( + arena: &'arena Arena, + ctx: InListContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_labeled_node(PredContextAll::InListContext(ctx)) + } + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a InListContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { + PredContextAll::InListContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut InListContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { + PredContextAll::InListContext(ctx) => Some(ctx), + _ => None + } + } else { + None + } + } +} + +impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for InListContext<'input, 'arena, Tok> +where + 'input: 'arena, + Tok: Token + 'input, +{ +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> InListContextExt<'input, 'arena, Tok> { + fn new(base: PredContextExt<'input, 'arena, Tok>) -> Self { + Self { + base, + pd: PhantomData + } + } + + fn copy_from(src: &mut GuardExprParserNode<'input, 'arena, Tok>) { + let invoking_state = src.get_invoking_state(); + let ctx = { + let Some(base_ctx): Option<&mut PredContext<'input, 'arena, Tok>> = src.as_rule_context_mut() else { + panic!("invalid node type for copy_from!"); + }; + let tmp = unsafe { std::ptr::read(base_ctx) }; + PredContextAll::InListContext(tmp.morph(|ext_src| Self::new(ext_src))) + }; + *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + src.set_invoking_state(invoking_state); + src.node_tag = >::node_tag(); + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn pred(&mut self,) -> Result<&'arena PredContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_pred)?; + let _local_ctx_fn = |recog: &Self| -> &'arena PredContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let mut _la: i32 = -1; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(55); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__1 |GuardExpr_T__6 |GuardExpr_T__7 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + CmpContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(48); + _la = recog.base.input.la(1); + if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 388) != 0)) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule value*/ + recog.base.set_state(49); + recog.value()?; + }} + GuardExpr_T__8 => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + InListContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena InListContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(50); + recog.base.match_token(GuardExpr_T__8,&mut recog.err_handler)?; + recog.base.set_state(51); + recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(52); + recog.expr_rec(0)?; + recog.base.set_state(53); + recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} +//------------------- value ---------------- +pub type ValueContextAll<'input, 'arena, Tok = CommonToken<'input>> = ValueContext<'input, 'arena, Tok>; + +pub type ValueContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ValueContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; +#[derive(Debug)] +pub struct ValueContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { + ph: PhantomData<(&'arena (), &'input Tok)>, +} + +impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ValueContextExt<'input, 'arena, Tok> +where + Tok: Token + 'input, +{ + type NodeKind = GuardExprParserNodeKind; + fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ValueContext } + fn get_rule_index(&self) -> usize { RULE_value } + fn make_node( + arena: &'arena Arena, + ctx: ValueContext<'input, 'arena, Tok>, + ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { + arena.alloc_zeroed_node(ctx)} + fn cast_from<'a>( + node: &'a GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a ValueContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ValueContext<'input, 'arena, Tok>)) + } else { + None + } + } + fn cast_from_mut<'a>( + node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, + ) -> Option<&'a mut ValueContext<'input, 'arena, Tok>> { + if node.node_tag() == >::node_tag() { + Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ValueContext<'input, 'arena, Tok>)) + } else { + None + } + } +} + +impl<'input: 'arena, 'arena, Tok: Token + 'input> ValueContextExt<'input, 'arena, Tok>{ + fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> + { + BaseParserRuleContext::create(arena, parent, invoking_state, ValueContextExt { + ph: PhantomData + } + ) + } +} + +pub trait ValueContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> +where + 'input: 'arena, + Tok: Token + 'input, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>>; + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>>; +} + +impl<'input, 'arena, Tok: Token + 'input> ValueContextAttrs<'input, 'arena, Tok> for ValueContext<'input, 'arena, Tok> +where + 'input: 'arena, +{ + /// Retrieves first TerminalNode corresponding to token ID + /// Returns `None` if there is no child corresponding to token ID + fn ID(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == GuardExpr_ID) + } + /// Retrieves first TerminalNode corresponding to token INT + /// Returns `None` if there is no child corresponding to token INT + fn INT(&self) -> Option<&TerminalNode<'input, 'arena, Tok>> { + self.children_of_type::>().into_iter().find(|child| child.symbol.get_token_type() == GuardExpr_INT) + } + fn expr(&self) -> Option<&'arena ExprContextAll<'input, 'arena, Tok>> { + self.child_of_type(0) + } +} + +impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> +where + 'input: 'arena, + TF: TokenFactory<'input, 'arena> + 'arena, + Input: TokenStream<'input, 'arena, TF> + 'arena, +{ + pub fn value(&mut self,) -> Result<&'arena ValueContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + dbt_antlr4::maybe_grow_stack!({ + let recog = self; + let _parentctx = recog.base.take_ctx(); + recog.base.enter_rule(ValueContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_value)?; + let _local_ctx_fn = |recog: &Self| -> &'arena ValueContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + let result: Result<(), ANTLRError> = (|| { + recog.base.set_state(63); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_ID => { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(57); + recog.base.match_token(GuardExpr_ID,&mut recog.err_handler)?; + }} + GuardExpr_INT => { + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(58); + recog.base.match_token(GuardExpr_INT,&mut recog.err_handler)?; + }} + GuardExpr_T__9 => { + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(59); + recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(60); + recog.expr_rec(0)?; + recog.base.set_state(61); + recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + Ok(()) + })(); + match result { + Ok(_)=>{}, + Err(e) if !e.is_recoverable() => return Err(e), + Err(ref re) => { + recog.err_handler.report_error(&mut recog.base, re); + recog.err_handler.recover(&mut recog.base, re)?; + } + } + recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) + }) + } +} + +// the serialized ATN is followed by 5 static SLL prediction tables (-Xstatic-dfa): +// decision 5: precedence-dispatched over cutoffs [1, 2], tables [2 3 4] +// decision 2: LL(*) cyclic, 35 states, 13 adaptive escapes, 1 guarded takes +// decision 4: LL(k), k=1, 3 states +// table 2 (decision 5): LL(k), k=1, 6 states +// table 3 (decision 5): LL(k), k=1, 7 states +// table 4 (decision 5): LL(k), k=0, 1 states +static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); +static _ATN: LazyLock = + LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); +static _serializedATN: [&'static str; 17] = [ + "CAIchAEEAA4ABAIOAgQEDgQEBg4GBAgOCAIACAAYEAAWABgAGgIAAgACAgICAgICAgICAgICAgICAgIG", + "AjYQAgIEAgQCBAYEQBAEAgQCBAYESBAEAgQCBAIEAgQCBAIECgRYEAQUBBgEXhIEAgYCBgIGAgYCBgIG", + "AgYGBnAQBgIIAggCCAIIAggCCAYIgAEQCAIIAAIICgAECAwQAAIEAAQEDhCKAQAWAgAAAAQ0AgAAAAhG", + "AgAAAAxuAgAAABB+AgAAABQYBgQCABYUAgAAABgaAgAAABoWAgAAABocAgAAABweAgAAAB4gCgAAAiAC", + "AgAAACIkCgIAACQmBggEACYoCgQAACgqBggEACosCgYAACw2AgAAAC4wBggEADAyCgYAADI2AgAAADQi", + "AgAAADQuAgAAADYGAgAAADg6DAQBADo+BhAIADxABgwGAD48AgAAAD5AAgAAAEBIAgAAAEJECggAAERI", + "BggEBkY4AgAAAEZCAgAAAEhaAgAAAEpMFAQAAExOCgoAAE5YBggEBlBSFAIAAFJUCgwAAFRYBggEBFZK", + "AgAAAFZQAgAAAFheAgAAAFpWAgAAAFpcAgAAAFwKAgAAAF5aAgAAAGBiDgAAAGJwBhAIAGRmChIAAGZo", + "ChQAAGhqBggEAGpsChYAAGxwAgAAAG5gAgAAAG5kAgAAAHAOAgAAAHKAAQoYAAB0gAEKGgAAdngKFAAA", + "eHoGCAQAenwKFgAAfIABAgAAAH5yAgAAAH50AgAAAH52AgAAAIABEgIAAAAQGjQ+RlZabn4OCgwERuoB", + "AAQABAQCAgQEAAAAAAACAAUABAQCAQEBAQEBAQECAQEBAQEEAAQAAAAAAAAEAgQEBAACAAQAAAAAAAAA", + "AAAAAAAAAAAAAAAqKjw8PDw8PDxOeIoBnAHGAcYB2AHYAeoB6gHqAeoB6gHqAeoB6gHqAeoB6gHqAeoB", + "6gHqAeoB6gHqAQEBAgQEBAYGBgoMCA4QChISDBYWDggIEBQUEhgaFAgIFhQUGBgaGgEBHAQEHgYGIAoM", + "Ig4QJBISJhYWKAgIKhQUGBgaGggILBQUGBgaLgEBAgQEMAYGBgoMMg4QNBISNhYWOAgIOhQUPBgaPggI", + "QBQUQhgaRAACIAICJAw6PEROVGIIBgwAAgQAAAAADAwMCgoCDAwEAAAAAAEMHgAEBAQCBAQAAAAAAAAe", + "Hh4eHh4BAQIEBAQGBgYKDAgWFgoAAAAAAQ4kAAQEBAIEBAQAAAAAAAAAJCQkJCQkJAEBAgQEBAYGBgoK", + "CAwMChYWDAAAAAABAgAEAAAAAAAAAAIKBAIEBAYI" +]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/lrdfaparser.rs b/runtime/Rust/tests/gen/lrdfaparser.rs index 6c8132aad4..c72aaa518c 100644 --- a/runtime/Rust/tests/gen/lrdfaparser.rs +++ b/runtime/Rust/tests/gen/lrdfaparser.rs @@ -1518,17 +1518,18 @@ where static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); -static _serializedATN: [&'static str; 12] = [ +static _serializedATN: [&'static str; 13] = [ "CAIaVAQADgAEAg4CAgACAAIAAgICAgICAgICAgYCGhACAgICAgICAgICAgICAgICAgICAgICAgICAgIC", "AgICAgICAgICAgICAgICAgIKAkoQAhQCGAJQEgICAgACBAQABAAEAgAMDgQACAgQEF4ACAIAAAAEGAIA", "AAAICgYEAgAKDAoAAAIMAgIAAAAOEAwCAQAQEgoIAAASGgYEAg4UGgoWAAAWGgoYAAAYDgIAAAAYFAIA", "AAAYFgIAAAAaTAIAAAAcHhQMAAAeIAoKAAAgSgYEAgwiJBQKAAAkJg4AAAAmSgYEAgwoKhQIAAAqLA4C", "AAAsSgYEAgouMBQGAAAwMgoSAAAyNAYEAgA0NgoUAAA2OAYEAgY4SgIAAAA6PBQSAAA8PgoCAAA+QAYE", "AgBAQgoEAABCSgIAAABERhQQAABGSgoGAABIHAIAAABIIgIAAABIKAIAAABILgIAAABIOgIAAABIRAIA", - "AABKUAIAAABMSAIAAABMTgIAAABOBgIAAABQTAIAAAAGGEhMDBAGAg4qAAoMBgIECAAAAAAAAAAAKioq", - "KioqKgICAgYGBAgIBgoKCAwOChAQBhISDAABECoABAIEAgICBAQAAAAAAAAAACoqKioqKioqAQECAgIE", - "BAQGBgYICBAKEhIMFBQOAAEKGAAEAgICBAAAAAAAGBgYGBgBAQICAgQGBgYIEAgAARI2AAQCBAIEAgQE", - "BAAAAAAAAAAAADY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBAQChISDhQUEAABChgABAICAgQAAAAA", - "ABgYGBgYAQECAgIEBgYGCgoIAAEQKgAEAgQCBAQEBAAAAAAAAAAAKioqKioqKioBAQICAgQEBAYGBggI", - "EAoSEgwUFA4AAQYMAAQCBAAAAAwMDAEBAgICBAABAgAEAAAAAAIEDAYICgwQEgIEBggKDA4=" + "AABKUAIAAABMSAIAAABMTgIAAABOBgIAAABQTAIAAAAGGEhMDhAGAg4qAAoMBgIECAAAAAAAAAAAKioq", + "KioqKgICAgYGBAgIBgoKCAwOChAQBhISDAAAAAABECoABAIEAgICBAQAAAAAAAAAACoqKioqKioqAQEC", + "AgIEBAQGBgYICBAKEhIMFBQOAAAAAAEKGAAEAgICBAAAAAAAGBgYGBgBAQICAgQGBgYIEAgAAAAAARI2", + "AAQCBAIEAgQEBAAAAAAAAAAAADY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBAQChISDhQUEAAAAAAB", + "ChgABAICAgQAAAAAABgYGBgYAQECAgIEBgYGCgoIAAAAAAEQKgAEAgQCBAQEBAAAAAAAAAAAKioqKioq", + "KioBAQICAgQEBAYGBggIEAoSEgwUFA4AAAAAAQYMAAQCBAAAAAwMDAEBAgICBAAAAAABAgAEAAAAAAAA", + "AAIEDAYICgwQEgIEBggKDA4=" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/parenexprparser.rs b/runtime/Rust/tests/gen/parenexprparser.rs index 34f9f30a9d..d331ee3624 100644 --- a/runtime/Rust/tests/gen/parenexprparser.rs +++ b/runtime/Rust/tests/gen/parenexprparser.rs @@ -1888,13 +1888,13 @@ static _serializedATN: [&'static str; 17] = [ "BggEADg6CgYAADpCAgAAADw+CggAAD5CBgQCBkASAgAAAEAWAgAAAEAYAgAAAEAsAgAAAEA0AgAAAEA8", "AgAAAEJUAgAAAERGFAQAAEZIDgAAAEhSBgQCBkpMFAIAAExODgIAAE5SBgQCBFBEAgAAAFBKAgAAAFJY", "AgAAAFRQAgAAAFRWAgAAAFYGAgAAAFhUAgAAAFpcChAAAFxqChIAAF5qChIAAGBiCgIAAGJkBggEAGRm", - "CgYAAGZqAgAAAGhaAgAAAGheAgAAAGhgAgAAAGoKAgAAAG4gAgAAAG4wAgAAAHJuBgQCAAwkQFBUaG4M", + "CgYAAGZqAgAAAGhaAgAAAGheAgAAAGhgAgAAAGoKAgAAAG4gAgAAAG4wAgAAAHJuBgQCAAwkQFBUaG4O", "CggCRPYBAAAMBAIAAAoAAAAAAAAAAAAGAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAGDY2NjZUZmZ4igGKAZwBogG0AcYB5AHkAeQB5AH2AfYB9gH2AfYB9gH2AfYB", "9gH2AfYB9gH2AfYB9gECAgIICAQSEgYUFAgCAgoICAwQEA4SEhAUFBICAhQICBYQEBgSEhoUFBwCAh4I", "CCASFBIEBCIGBiQIDiYEBCIGBigIDiYCAioICCASFBwSEiwEBC4GBjAIDjIEBC4GBjQIDjICAjYICCAQ", "EDgSEjoUFDwCAj4ICEASFEIgFAYGCAogBAYIJAQICioEBggsBgYICi4EBggwBgYICjIEBgg0BAYINgQG", - "CDgEBgg6BAYIPAQGCD4EBghABAYIQgQGCAQGEgAEAgAAAAASEhIICAIKDAQODgIAAQoYAAQEBAIEAAAA", - "AAAYGBgYGAEBAgQEBAYGBggOCAABDCQABAQEBAIEAAAAAAAAJCQkJCQkAQECBAQEBgYGCAgICgwKDg4I", - "AAECAAQAAAAAAgYEAgQEBgg=" + "CDgEBgg6BAYIPAQGCD4EBghABAYIQgQGCAAAAAQGEgAEAgAAAAASEhIICAIKDAQODgIAAAAAAQoYAAQE", + "BAIEAAAAAAAYGBgYGAEBAgQEBAYGBggOCAAAAAABDCQABAQEBAIEAAAAAAAAJCQkJCQkAQECBAQEBgYG", + "CAgICgwKDg4IAAAAAAECAAQAAAAAAAAAAgYEAgQEBgg=" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index 1325e4d194..7309ace0e6 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -1830,8 +1830,8 @@ static _serializedATN: [&'static str; 14] = [ "AAAAWFQCAAAAWFoCAAAAWl4CAAAAXFgCAAAAXmAKEAAAYGIKFAAAYg4CAAAAZGYKEAAAZmoKEgAAaGQC", "AAAAamwCAAAAbGgCAAAAbG4CAAAAbnACAAAAcHIKEAAAcnQKFAAAdBICAAAAdngKEAAAeHwKEgAAenYC", "AAAAenwCAAAAfH4CAAAAfoABChAAAIABggEKFAAAggEWAgAAAIQBhgEKFgAAhgGOAQoYAACIAYoBChYA", - "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEMDA4AChgAAAYCBAAAAAAAAAwY", - "GBgYAgICCAgEBAQGBgYIAAIKHgAABAIAAAQAAAAABhgYGB4aGgIBAQQKCgYODggaGgIABggSAAACBAAA", - "AAAABhISEhAQAhISBBQUBgAICBIAAAIEAAAAAAAGEhISEBACEhIEFBQGAAoIEgAAAgQAAAAAAAYSEhIQ", - "EAISEgQUFAYADAYMAAACAAAAAAYMDBYWAhgYBAAA" + "AIoBjgEKGAAAjAGEAQIAAACMAYgBAgAAAI4BGgIAAAAOLjxKWGx6jAEODA4AChgAAAYCBAAAAAAAAAwY", + "GBgYAgICCAgEBAQGBgYIAAAAAAIKHgAABAIAAAQAAAAABhgYGB4aGgIBAQQKCgYODggaGgIAAAAABggS", + "AAACBAAAAAAABhISEhAQAhISBBQUBgAAAAAICBIAAAIEAAAAAAAGEhISEBACEhIEFBQGAAAAAAoIEgAA", + "AgQAAAAAAAYSEhIQEAISEgQUFAYAAAAADAYMAAACAAAAAAYMDBYWAhgYBAAAAAAA" ]; \ No newline at end of file diff --git a/runtime/Rust/tests/guard_differential_tests.rs b/runtime/Rust/tests/guard_differential_tests.rs new file mode 100644 index 0000000000..6c3ef72f06 --- /dev/null +++ b/runtime/Rust/tests/guard_differential_tests.rs @@ -0,0 +1,141 @@ +//! Differential corners for the guarded-take escape of the +//! optional-postfix take rule (grammar `grammars/GuardExpr.g4`, generated +//! twice: `gen/guardexprparser.rs` with `-Xstatic-dfa`, +//! `gen/adaptive/guardexprparser.rs` without). +//! +//! The grammar mirrors the dbt SQL shape (Bigquery's +//! `UPDATE SET targets+=expression EQ values+=expression`): the +//! assignment's first `expr` is followed by `'='`, which is also the +//! comparison operator of the optional postfix predicate, so the +//! predicate decision's take/skip conflict is genuinely +//! context-sensitive - inside an assignment target skip must win +//! (`set a = b ;` assigns b to a), everywhere else take wins +//! (`a = b ;` is a comparison). The static table resolves the conflict +//! to take guarded by a stack test that defers to adaptivePredict when +//! the epsilon-pop chase from the decision's block end can reach the +//! assignment's `'='` position. Both engines must agree on every corner +//! (tree or error). + +#[rustfmt::skip] +mod gen { + #![allow(non_snake_case)] + #![allow(clippy::all)] + pub mod guardexprlexer; + pub mod guardexprlistener; + pub mod guardexprparser; + pub mod adaptive { + pub mod guardexprlexer; + pub mod guardexprlistener; + pub mod guardexprparser; + } +} + +use dbt_antlr4::common_token_stream::CommonTokenStream; +use dbt_antlr4::recognizer::Recognizer; +use dbt_antlr4::token_factory::CommonTokenFactory; +use dbt_antlr4::trees::string_tree; +use dbt_antlr4::{Arena, InputStream}; + +fn parse_static(input: &str) -> Result { + Arena::with(|arena| { + let lexer = gen::guardexprlexer::GuardExprLexer::<_, CommonTokenFactory>::new( + arena, + InputStream::new(input), + ); + let tokens = CommonTokenStream::new(lexer); + let mut parser = gen::guardexprparser::GuardExprParser::new(arena, tokens); + parser + .prog() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + .map_err(|e| format!("{e:?}")) + }) +} + +fn parse_adaptive(input: &str) -> Result { + Arena::with(|arena| { + let lexer = gen::adaptive::guardexprlexer::GuardExprLexer::<_, CommonTokenFactory>::new( + arena, + InputStream::new(input), + ); + let tokens = CommonTokenStream::new(lexer); + let mut parser = gen::adaptive::guardexprparser::GuardExprParser::new(arena, tokens); + parser + .prog() + .map(|ctx| string_tree(ctx, parser.get_rule_names())) + .map_err(|e| format!("{e:?}")) + }) +} + +/// Corners of the assignment/comparison dangling-else. Both engines must +/// agree on every one (tree or error). +const CORNERS: &[&str] = &[ + // take wins outside assignments: comparisons + "a = b ;", + "a < b ;", + "a > 1 ;", + "a = b = c ;", + "a IN ( b ) ;", + "a = b AND c = d ;", + // skip wins inside assignment targets + "set a = b ;", + "set a = 1 ;", + "set ab = cd ;", + // the assignment value is itself a comparison: the value-side + // decision is sealed off from the assignment's '=' and must take + "set a = b = c ;", + "set a = b < c ;", + "set a = b AND c ;", + "set a = b AND c = d ;", + // multiple statements: guard state per statement + "set a = b ; c = d ;", + "a = b ; set c = d ; e = f ;", + "set a = b ; set c = d ;", + // parentheses seal the expression: comparisons inside, even in an + // assignment value (the chase must stop at the paren frame) + "set x = ( a = b ) ;", + "set x = ( a ) = b ;", + "( a = b ) ;", + "( a ) = b ;", + "set ( a ) = b ;", + // IN: a second predicate-start token + "a IN ( b ) ;", + "set a = b IN ( c ) ;", + "a IN ( b = c ) ;", + // boolean operators: right operands, chase through the loop frames + "a AND b = c ;", + "set a = b AND c ;", + "a AND set ;", + "NOT a = b ;", + "set a = NOT b = c ;", + "a OR b AND c = d OR e ;", + "set x = a OR b = c AND d ;", + // nested assignments are not a thing: the second 'set' starts a new + // statement only after ';' + "set a = b ; set c = d = e ;", + // errors: both engines must fail identically + "set a = ;", + "set = b ;", + "a = ;", + "set a b ;", + "a IN ( ;", + "set a = b", + "( a = b ;", + "a AND ;", +]; + +#[test] +fn test_corners_differential() { + for input in CORNERS { + let s = parse_static(input); + let a = parse_adaptive(input); + assert_eq!( + a.is_ok(), + s.is_ok(), + "parse outcome diverges on {input:?}\nadaptive: {a:?}\nstatic: {s:?}" + ); + assert_eq!( + a, s, + "parse tree diverges on {input:?}\nadaptive: {a:?}\nstatic: {s:?}" + ); + } +} diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index d756f76033..c89f6f8d48 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -192,6 +192,7 @@ public static class Result { /** Dry-run: conflict states where the optional-postfix take rule * fires (mirror + vetoes pass): would accept take (alt 1). */ public int takeRuleFires; + public int guardedTakes; /** Conflict states resolved to min(U) by the uniform-widening * trust (every context entry has an assured min attestation). */ public int utrustResolutions; @@ -275,6 +276,26 @@ public Result(DecisionState decisionState) { */ protected static final int FOREIGN_CONSUME_TAINT = 8; + /** + * Taint for rooted configurations of the optional-postfix + * guard analysis: a skip-lineage (alt 2) configuration that consumed a + * token outside the decision's dangling-else discipline - at an ATN + * state outside the decision rule whose context's deepest frame is not + * a return into the decision's block end (see the optional-postfix + * take rule). The consumption position (or the invocation site of the + * non-mirror deepest frame) is recorded as a guard root: a + * runtime stack can realize such a configuration only when its + * epsilon-pop chase from the block end reaches a root position, which + * is exactly what the guarded-take escape evaluates (see + * {@link #finalizeGuardedTakes}). Assigned above every other taint bit + * so configuration merging (which takes the numeric max) never loses + * it; the bit is consulted only by the postfix guard analysis, and + * conflicts involving rooted skip configurations are treated as hard + * for exact-ambiguity trust (a merge may have hidden a hard bit + * beneath it). + */ + protected static final int ROOTED_TAINT = 16; + /** Taint for configurations whose calling context was widened. */ protected static final int WIDENED_TAINT = 4; @@ -575,6 +596,14 @@ protected SharedDescentAnalyzer descentAnalyzer() { /** Optional-postfix shape of the decision under construction; null * when the decision is not an optional-postfix (X Y?) shape. */ protected OptionalPostfixAnalyzer.Shape currentPostfixShape; + /** Rule index of the decision under construction (postfix guard + * analysis: consumption inside this rule is within the dangling-else + * discipline and never marks {@link #ROOTED_TAINT}). */ + protected int currentDecisionRule = -1; + /** Lazily built: a rule call's follow state -> the call-site state + * owning the {@link RuleTransition} (the invoking state a real parse + * stack carries for that call). */ + protected Map siteByFollowState; public DecisionClassifier(Grammar g) { this.g = g; @@ -963,6 +992,24 @@ protected Result classifyPrecedence(DecisionState s) { return res; } + /** Lazily built {@link #siteByFollowState}. */ + protected Map siteByFollowState() { + if (siteByFollowState == null) { + siteByFollowState = new HashMap(); + for (ATNState st : atn.states) { + if (st == null) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + siteByFollowState.put(((RuleTransition)t).followState.stateNumber, + st.stateNumber); + } + } + } + } + return siteByFollowState; + } + /** Lazily built {@link #callByFollowState}. */ protected Map callByFollowState() { if (callByFollowState == null) { @@ -1124,7 +1171,7 @@ protected Set applyPrecedenceFilter(Set raw) { for (ATNConfig c : raw) { long key = ((long)c.state.stateNumber << 32) | c.alt; Integer prev = taintByStateAlt.get(key); - int taint = c.reachesIntoOuterContext & (BOUNDARY_TAINT|PRECPRED_TAINT|WIDENED_TAINT); + int taint = c.reachesIntoOuterContext & (BOUNDARY_TAINT|PRECPRED_TAINT|WIDENED_TAINT|ROOTED_TAINT); taintByStateAlt.put(key, prev == null ? taint : (prev|taint)); } @@ -1175,6 +1222,9 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List acceptMasks = new ArrayList(); // 0 = not a mask-accept state List fallbackAlts = new ArrayList(); // 0 = none List stateDepth = new ArrayList(); // lookahead depth (BFS layer) + List> ownRoots = new ArrayList>(); // postfix guard roots entering each state + List guardCandidates = new ArrayList(); // take-vetoed conflict states + this.currentDecisionRule = s.ruleIndex; Set start = new LinkedHashSet(); Set startBusy = new HashSet(1024); @@ -1205,6 +1255,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { acceptMasks.add(0L); fallbackAlts.add(0); stateDepth.add(0); + ownRoots.add(null); Deque work = new ArrayDeque(); work.add(0); @@ -1242,6 +1293,13 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { boolean allBoundary = true; for (ATNConfig c : cs) { if ((c.reachesIntoOuterContext & WIDENED_TAINT) != 0) widenedTainted = true; + // a rooted skip configuration may have absorbed a hard + // taint bit in a max-merge (ROOTED_TAINT outranks them + // all): never trust a conflict it participates in + if (c.alt == 2 && currentPostfixShape != null + && (c.reachesIntoOuterContext & ROOTED_TAINT) != 0) { + widenedTainted = true; + } if ((c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0) anyBoundary = true; else allBoundary = false; } @@ -1403,9 +1461,27 @@ && hasPendingPrecReturn(c.context)) { } continue; } - else if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { - System.err.printf("TAKE-VETO d=%d state=%d exact=%s foreign=%s mirror=%s realTake=%s%n", - s.decision, d, exact, skipForeign, mirrorOk, realTake); + if ("postfix".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("TAKE-VETO d=%d state=%d exact=%s foreign=%s mirror=%s realTake=%s blockEnd=%d rule=%s%n", + s.decision, d, exact, skipForeign, mirrorOk, realTake, + currentPostfixShape.blockEndState, g.getRule(s.ruleIndex).name); + for (ATNConfig c : cs) { + if (c.alt == 2 && c.state.ruleIndex != s.ruleIndex + && !bottomFrameIs(c.context, + currentPostfixShape.blockEndState, + java.util.Collections.newSetFromMap( + new java.util.IdentityHashMap()))) { + System.err.printf(" NOMIRROR skip %s:%d taint=%d ctx=%s%n", + g.getRule(c.state.ruleIndex).name, c.state.stateNumber, + c.reachesIntoOuterContext, decodeContext(c.context)); + } + } + } + if (hybridMode && !skipForeign && realTake) { + // vetoed only by the mirror check: a candidate for + // the guarded-take escape (resolved after + // construction, once guard roots have propagated) + guardCandidates.add(d); } } @@ -1602,8 +1678,14 @@ else if (abortInfAsOverflow) { acceptMasks.add(0L); fallbackAlts.add(0); stateDepth.add(stateDepth.get(d)+1); + ownRoots.add(ls.roots); work.add(id); } + else if (ls.roots != null) { + Set acc = ownRoots.get(id); + if (acc == null) ownRoots.set(id, new HashSet(ls.roots)); + else acc.addAll(ls.roots); + } edges.get(d).add(id); edgeLabels.get(d).add(ls.label); } @@ -1633,6 +1715,17 @@ else if (abortInfAsOverflow) { boolean cyclic = isCyclic(edges); if (!cyclic) res.k = longestPath(edges); + // Take-vetoed conflict states get a second chance: the + // guarded-take escape (see finalizeGuardedTakes). + List guardAlts = new ArrayList( + java.util.Collections.nCopies(states.size(), 0)); + GuardData guard = null; + if (hybridMode && currentPostfixShape != null && !guardCandidates.isEmpty() + && !overflow && !res.sawPredicate) { + guard = finalizeGuardedTakes(s, states, edges, acceptAlts, acceptMasks, + ownRoots, guardCandidates, guardAlts, res); + } + if ("states".equals(System.getProperty("antlr.dfa.debug")) && String.valueOf(currentDecisionNumber).equals(System.getProperty("antlr.dfa.debug.decision"))) { dumpStates(s, states, edges, edgeLabels, acceptAlts, stateDepth); @@ -1649,7 +1742,9 @@ else if (abortInfAsOverflow) { res.escapes = escapes; res.coverage = startCoverage(edges, edgeLabels, acceptAlts, acceptMasks); if (acceptAlts.get(0) != StaticDFA.ESCAPE && res.coverage >= hybridMinCoverage) { - res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, acceptMasks, fallbackAlts, cyclic, res.k); + res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, acceptMasks, + fallbackAlts, cyclic, res.k, guardAlts, + guard != null ? guard.danger : null, guard != null ? guard.pass : null); } return false; } @@ -1663,11 +1758,249 @@ else if (abortInfAsOverflow) { if (res.category == Category.LLK || res.category == Category.LLSTAR || res.category == Category.EXACT_AMBIG) { - res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, acceptMasks, fallbackAlts, cyclic, res.k); + res.dfa = toStaticDFA(s.decision, edgeLabels, edges, acceptAlts, acceptMasks, + fallbackAlts, cyclic, res.k, null, null, null); } return false; } + /** Danger/pass state sets of a decision's guarded-take escapes (see + * {@link #finalizeGuardedTakes}); null when the decision has none. */ + protected static final class GuardData { + /** Sorted invoking states whose follow state's epsilon-reachable + * region contains a guard root: the runtime guard defers when the + * parse stack carries one. */ + final int[] danger; + /** Sorted invoking states whose follow state can reach their rule's + * stop state over epsilon: the runtime guard keeps walking the + * stack past them. */ + final int[] pass; + GuardData(int[] danger, int[] pass) { this.danger = danger; this.pass = pass; } + } + + /** + * Second chance for take-vetoed conflicts of an optional-postfix + * decision ({@code X Y?}): the veto means some skip (alt 2) + * configuration left the dangling-else discipline - it consumed tokens + * at positions not funneled through the decision's own take path (the + * mirror check). Such a configuration is realizable on a runtime parse + * stack only when the stack's epsilon-pop chase from the decision's + * block end reaches the guard root its first out-of-discipline + * consumption passed through (recorded as {@link #ROOTED_TAINT} plus + * per-state root sets during construction): the chase is how the + * full-context simulator's closure actually reaches that position, + * and the runtime never consults the grammar-wide FOLLOW union the + * tool-side SLL closure uses. A vetoed conflict state whose skip + * configurations are all in-discipline, mirror-bottomed, or rooted + * therefore resolves to take, guarded by a runtime stack test: + * defer to {@code adaptivePredict} iff the chase can reach a root. + * On every stack where the guard passes, no out-of-discipline skip + * configuration exists at runtime, the mirror argument covers the + * rest, and take is the adaptive engine's answer (or the input is + * invalid, the accepted error-path divergence class). + * + *

Bails (all conservative): a widening-born skip configuration + * (analysis artifact, murky realizability), a clean out-of-discipline + * skip configuration (no root recorded - the guard could not catch + * it), a root reachable from the block end without popping any frame + * (the guard would fire on every stack - useless), or a decision rule + * whose block end cannot reach the rule stop over epsilon (the chase + * can never pop out, the guard can never fire - resolves to plain + * take accepts instead).

+ * + * @return the guard's danger/pass sets, or null when no candidate + * state resolved as a guarded take + */ + protected GuardData finalizeGuardedTakes(DecisionState s, + List> states, + List> edges, + List acceptAlts, + List acceptMasks, + List> ownRoots, + List guardCandidates, + List guardAlts, + Result res) { + int n = states.size(); + // propagate guard roots through the edge graph to a fixpoint: + // through[s] = own[s] ∪ ∪_{p→s} through[p] + List> through = new ArrayList>(n); + Deque rq = new ArrayDeque(); + for (int i = 0; i < n; i++) { + Set own = ownRoots.get(i); + through.add(own != null ? new HashSet(own) : null); + if (own != null) rq.add(i); + } + while (!rq.isEmpty()) { + int p = rq.remove(); + Set rp = through.get(p); + for (int t : edges.get(p)) { + Set rt = through.get(t); + if (rt == null) { + through.set(t, new HashSet(rp)); + rq.add(t); + } + else if (rt.addAll(rp)) { + rq.add(t); + } + } + } + + Set G = new HashSet(); + List guarded = new ArrayList(); + for (int d : guardCandidates) { + if (acceptAlts.get(d) != StaticDFA.ESCAPE || acceptMasks.get(d) != 0) continue; + Set roots = through.get(d); + if (roots == null || roots.isEmpty()) continue; + boolean eligible = true; + for (ATNConfig c : states.get(d)) { + if (c.alt != 2) continue; + int taint = c.reachesIntoOuterContext; + if ((taint & WIDENED_TAINT) != 0) { eligible = false; break; } + if (c.state.ruleIndex == s.ruleIndex) continue; + if ((taint & ROOTED_TAINT) != 0) continue; + if (bottomFrameIs(c.context, currentPostfixShape.blockEndState, + java.util.Collections.newSetFromMap( + new java.util.IdentityHashMap()))) { + continue; + } + eligible = false; + break; + } + if (!eligible) continue; + acceptAlts.set(d, StaticDFA.GUARDED); + guardAlts.set(d, 1); + guarded.add(d); + G.addAll(roots); + res.guardedTakes++; + if ("guard".equals(System.getProperty("antlr.dfa.debug")) + || "postfix".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("GUARD-TAKE d=%d state=%d roots=%s%n", + s.decision, d, new TreeSet(roots)); + } + } + if (guarded.isEmpty()) return null; + + Set reach0 = reachEps(currentPostfixShape.blockEndState); + reach0.retainAll(G); + if (!reach0.isEmpty()) { + // a root is epsilon-reachable from the block end without popping + // any frame: the guard would defer on every stack - useless + for (int d : guarded) { + acceptAlts.set(d, StaticDFA.ESCAPE); + guardAlts.set(d, 0); + res.guardedTakes--; + } + return null; + } + RuleStopState stop = atn.ruleToStopState[s.ruleIndex]; + if (stop == null || !reachEps(currentPostfixShape.blockEndState) + .contains(stop.stateNumber)) { + // the chase can never leave the decision rule: no root is + // reachable on any stack - plain take accepts + for (int d : guarded) { + acceptAlts.set(d, 1); + guardAlts.set(d, 0); + res.guardedTakes--; + res.takeRuleFires++; + } + return null; + } + + // danger[s]: an invoking state whose follow's epsilon-reachable + // region contains a guard root; pass[s]: the follow can reach its + // own rule's stop (the chase may keep popping). Exotic states with + // several rule transitions: danger = any follow, pass = all follows + // (conservative in both directions). + List danger = new ArrayList(); + List pass = new ArrayList(); + for (ATNState st : atn.states) { + if (st == null) continue; + boolean anyDanger = false; + boolean allPass = true; + boolean hasCall = false; + RuleStopState rs = atn.ruleToStopState[st.ruleIndex]; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (!(t instanceof RuleTransition)) continue; + hasCall = true; + Set r = reachEps(((RuleTransition)t).followState.stateNumber); + Set hit = new HashSet(r); + hit.retainAll(G); + if (!hit.isEmpty()) anyDanger = true; + if (rs == null || !r.contains(rs.stateNumber)) allPass = false; + } + if (!hasCall) continue; + if (anyDanger) danger.add(st.stateNumber); + if (allPass) pass.add(st.stateNumber); + } + return new GuardData(danger.stream().mapToInt(Integer::intValue).sorted().toArray(), + pass.stream().mapToInt(Integer::intValue).sorted().toArray()); + } + + /** + * ATN states epsilon-reachable from {@code start} (inclusive), + * following epsilon transitions - rule invocations descend into the + * callee - but never crossing a rule stop state (the grammar-wide + * FOLLOW links attached to stop states are the tool-side SLL closure's + * business, not the runtime chase's; see {@link #finalizeGuardedTakes}). + */ + protected Set reachEps(int start) { + Set out = new HashSet(); + Deque wl = new ArrayDeque(); + wl.add(start); + while (!wl.isEmpty()) { + int sn = wl.remove(); + if (!out.add(sn)) continue; + ATNState st = atn.states.get(sn); + if (st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t.isEpsilon()) wl.add(t.target.stateNumber); + } + } + return out; + } + + /** + * Guard roots of one out-of-discipline skip consumption: the + * consumption's own ATN position for context branches that bottom out + * at the empty context (the epsilon-pop chase must reach the position + * itself), and the call-site state of every non-mirror deepest context + * frame (the chase must reach the site to push that frame). Mirror + * branches (deepest frame = the decision's block end) contribute + * nothing - they are realizable through the decision's own take path. + */ + protected void collectGuardRoots(ATNConfig c, Set out) { + collectGuardRoots(c, c.context, out, + java.util.Collections.newSetFromMap( + new java.util.IdentityHashMap())); + } + + private void collectGuardRoots(ATNConfig c, PredictionContext ctx, Set out, + Set visited) { + if (ctx == null || ctx.isEmpty()) { + out.add(c.state.stateNumber); + return; + } + if (!visited.add(ctx)) return; + for (int i = 0; i < ctx.size(); i++) { + PredictionContext p = ctx.getParent(i); + if (p == null || p.isEmpty()) { + int rs = ctx.getReturnState(i); + if (rs == PredictionContext.EMPTY_RETURN_STATE) { + out.add(c.state.stateNumber); + } + else if (rs != currentPostfixShape.blockEndState) { + Integer site = siteByFollowState().get(rs); + out.add(site != null ? site : rs); + } + } + else { + collectGuardRoots(c, p, out, visited); + } + } + } + /** * Hot-path coverage proxy of a hybrid table: the fraction of the start * state's outgoing token space whose successor subgraph contains at @@ -1691,7 +2024,8 @@ protected static double startCoverage(List> edges, boolean[] reachesAccept = new boolean[n]; Deque work = new ArrayDeque(); for (int i = 0; i < n; i++) { - if (acceptAlts.get(i) > 0 || acceptMasks.get(i) != 0) { + if (acceptAlts.get(i) > 0 || acceptAlts.get(i) == StaticDFA.GUARDED + || acceptMasks.get(i) != 0) { reachesAccept[i] = true; work.add(i); } @@ -1769,17 +2103,21 @@ protected static StaticDFA toStaticDFA(int decision, List acceptAlts, List acceptMasks, List fallbackAlts, - boolean cyclic, int maxK) { + boolean cyclic, int maxK, + List guardAlts, + int[] guardDanger, int[] guardPass) { int n = edgeTargets.size(); int[] accepts = new int[n]; long[] masks = new long[n]; int[] fallbacks = new int[n]; + int[] guarded = new int[n]; int[] offsets = new int[n+1]; List triples = new ArrayList(); for (int s = 0; s < n; s++) { accepts[s] = acceptAlts.get(s); masks[s] = acceptMasks.get(s); fallbacks[s] = fallbackAlts.get(s); + if (guardAlts != null) guarded[s] = guardAlts.get(s); offsets[s] = triples.size()*3; List stateTriples = new ArrayList(); for (int e = 0; e < edgeTargets.get(s).size(); e++) { @@ -1799,16 +2137,21 @@ protected static StaticDFA toStaticDFA(int decision, edges[i*3+1] = triples.get(i)[1]; edges[i*3+2] = triples.get(i)[2]; } - return new StaticDFA(decision, n, accepts, masks, fallbacks, offsets, edges, cyclic, maxK); + return new StaticDFA(decision, n, accepts, masks, fallbacks, offsets, edges, + cyclic, maxK, guarded, guardDanger, guardPass); } /** A DFA edge under construction: token class label -> successor config set. */ protected static final class LabeledSuccessor { final IntervalSet label; final Set configs; - LabeledSuccessor(IntervalSet label, Set configs) { + /** Guard roots passed through by skip-lineage consumption on this + * edge (optional-postfix guard analysis); null/empty when none. */ + final Set roots; + LabeledSuccessor(IntervalSet label, Set configs, Set roots) { this.label = label; this.configs = configs; + this.roots = roots; } } @@ -1911,9 +2254,24 @@ else if (t instanceof WildcardTransition) { // close each class; merge classes that reach the same successor set Map bySuccessor = new LinkedHashMap(); + Map> rootsBySuccessor = new LinkedHashMap>(); for (Map.Entry e : classLabels.entrySet()) { BitSet key = e.getKey(); + if ("move".equals(System.getProperty("antlr.dfa.debug")) + && String.valueOf(currentDecisionNumber).equals(System.getProperty("antlr.dfa.debug.decision"))) { + StringBuilder sb = new StringBuilder(); + sb.append("MOVE d=").append(currentDecisionNumber) + .append(" label=").append(e.getValue().toString(g.getVocabulary())).append('\n'); + for (int m = key.nextSetBit(0); m >= 0; m = key.nextSetBit(m+1)) { + ATNConfig c = moveConfigs.get(m); + sb.append(String.format(" alt=%d %s:%d taint=%d stop=%s ctx=%s%n", + c.alt, g.getRule(c.state.ruleIndex).name, c.state.stateNumber, + c.reachesIntoOuterContext, moveIsStop.get(m), decodeContext(c.context))); + } + System.err.print(sb); + } Set succ = new LinkedHashSet(); + Set succRoots = null; Set busy = new HashSet(1024); for (int m = key.nextSetBit(0); m >= 0; m = key.nextSetBit(m+1)) { ATNConfig c = moveConfigs.get(m); @@ -1944,6 +2302,24 @@ else if (t instanceof WildcardTransition) { } } } + if (currentPostfixShape != null && c.alt == 2 + && (c.reachesIntoOuterContext & ROOTED_TAINT) == 0 + && c.state.ruleIndex != currentDecisionRule + && !bottomFrameIs(c.context, + currentPostfixShape.blockEndState, + java.util.Collections.newSetFromMap( + new java.util.IdentityHashMap()))) { + // skip-lineage consumption outside the dangling-else + // discipline (a position outside the decision rule whose + // context does not bottom out at the block end): the + // advanced configuration is realizable only on runtime + // stacks whose epsilon-pop chase from the block end + // reaches the root position(s) this consumption passed + // through - record them for the guarded-take escape. + advanced.reachesIntoOuterContext |= ROOTED_TAINT; + if (succRoots == null) succRoots = new HashSet(); + collectGuardRoots(c, succRoots); + } closure(advanced, succ, busy, res, 0); } } @@ -1952,15 +2328,22 @@ else if (t instanceof WildcardTransition) { IntervalSet merged = bySuccessor.get(succKey); if (merged == null) { bySuccessor.put(succKey, e.getValue()); + if (succRoots != null) rootsBySuccessor.put(succKey, succRoots); } else { merged.addAll(e.getValue()); + if (succRoots != null) { + Set acc = rootsBySuccessor.get(succKey); + if (acc == null) rootsBySuccessor.put(succKey, succRoots); + else acc.addAll(succRoots); + } } } - List result = new ArrayList(bySuccessor.size()); + List result = new ArrayList(); for (Map.Entry e : bySuccessor.entrySet()) { - result.add(new LabeledSuccessor(e.getValue(), e.getKey().set)); + result.add(new LabeledSuccessor(e.getValue(), e.getKey().set, + rootsBySuccessor.get(e.getKey()))); } return result; } @@ -2797,14 +3180,15 @@ else if (r.dfa == null) { "factorable: %d decisions (%d groups); mask-accepts=%d states; escapes curable=%d%n", factorDecisions, factorGroups, factorMaskStates, factorCured)); } - int postfixDecisions = 0, takeFires = 0; + int postfixDecisions = 0, takeFires = 0, guardedTakes = 0; for (Result r : results) { if (r.hasPostfixShape) postfixDecisions++; takeFires += r.takeRuleFires; + guardedTakes += r.guardedTakes; } if (postfixDecisions > 0) { - buf.append(String.format("take-rule: %d optional-postfix decisions; fires at %d conflict states%n", - postfixDecisions, takeFires)); + buf.append(String.format("take-rule: %d optional-postfix decisions; fires at %d conflict states; guarded takes=%d%n", + postfixDecisions, takeFires, guardedTakes)); } int utrust = 0; for (Result r : results) utrust += r.utrustResolutions; @@ -2873,7 +3257,8 @@ else if (r.dfa == null) { .append(']'); } if (r.hasPostfixShape) { - buf.append(" [postfix: takeFires=").append(r.takeRuleFires).append(']'); + buf.append(" [postfix: takeFires=").append(r.takeRuleFires) + .append(" guarded=").append(r.guardedTakes).append(']'); } buf.append('\n'); } diff --git a/tool/src/org/antlr/v4/analysis/StaticDFA.java b/tool/src/org/antlr/v4/analysis/StaticDFA.java index ed0c17507d..f49a8d0f62 100644 --- a/tool/src/org/antlr/v4/analysis/StaticDFA.java +++ b/tool/src/org/antlr/v4/analysis/StaticDFA.java @@ -35,6 +35,27 @@ public class StaticDFA { */ public static final int ESCAPE = -1; + /** + * Sentinel in {@link #accepts}: a guarded-take state of an + * optional-postfix decision ({@code X Y?}). The walker evaluates the + * decision's guard - the epsilon-pop chase from the decision's block + * end over the real parse stack - and resolves to + * {@link #guardedAlts}{@code [s]} when no invoking state on the stack + * is in {@link #guardDanger}, deferring to {@code adaptivePredict} + * otherwise (see DecisionClassifier#finalizeGuardedTakes). + */ + public static final int GUARDED = -3; + + /** True if any state of this table is a guarded-take state: a runtime + * prediction driven by it may defer to {@code adaptivePredict} when + * the parse stack trips the guard. */ + public boolean hasGuards() { + for (int a : accepts) { + if (a == GUARDED) return true; + } + return false; + } + /** True if any state of this table is an escape state: a runtime * prediction driven by it can defer to {@code adaptivePredict}. */ public boolean hasEscapes() { @@ -85,9 +106,27 @@ public boolean hasMasks() { public final boolean cyclic; /** Max lookahead depth if acyclic; -1 if cyclic. */ public final int maxK; + /** + * Resolution alternative per {@link #GUARDED} state; 0 = not guarded. + */ + public final int[] guardedAlts; + /** + * Sorted invoking-state numbers whose follow state's epsilon-reachable + * region contains a guard root of this decision; null/empty when the + * table has no guarded states. The runtime guard defers when the parse + * stack carries one of these invoking states. + */ + public final int[] guardDanger; + /** + * Sorted invoking-state numbers whose follow state can reach their own + * rule's stop over epsilon; the runtime guard keeps walking the stack + * past them (and stops at the first invoking state not in this set). + */ + public final int[] guardPass; public StaticDFA(int decision, int numStates, int[] accepts, long[] acceptMasks, - int[] fallbacks, int[] edgeOffsets, int[] edges, boolean cyclic, int maxK) { + int[] fallbacks, int[] edgeOffsets, int[] edges, boolean cyclic, int maxK, + int[] guardedAlts, int[] guardDanger, int[] guardPass) { this.decision = decision; this.numStates = numStates; this.accepts = accepts; @@ -97,5 +136,8 @@ public StaticDFA(int decision, int numStates, int[] accepts, long[] acceptMasks, this.edges = edges; this.cyclic = cyclic; this.maxK = maxK; + this.guardedAlts = guardedAlts; + this.guardDanger = guardDanger; + this.guardPass = guardPass; } } diff --git a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java index 47e57fca36..e8715917bd 100644 --- a/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java +++ b/tool/src/org/antlr/v4/codegen/model/SerializedStaticDFAs.java @@ -41,16 +41,33 @@ * fallbacks[numStates] (error-avoidance alt per state; 0 = none) * edgeOffsets[numStates+1] (index of each state's first edge int) * edges[numEdgeInts] ((lo, hi, target) triples, lo-sorted per state) - * numMaskStates (states accepting with an alternative - * mask instead of a unique alt: the live - * set is covered by one prefix-factor - * group; the parser executes the shared - * prefix and resolves at the tail decision) - * for each mask state: (sorted by state index) - * state - * numAlts - * alts[numAlts] (the group's member alternatives) - * numPrecedenceDispatches + * numMaskStates (states accepting with an alternative + * mask instead of a unique alt: the live + * set is covered by one prefix-factor + * group; the parser executes the shared + * prefix and resolves at the tail decision) + * for each mask state: (sorted by state index) + * state + * numAlts + * alts[numAlts] (the group's member alternatives) + * numGuardedStates (guarded-take states of an + * optional-postfix decision: the walker + * evaluates the decision's stack guard and + * resolves to the given alternative when + * it passes, deferring to adaptivePredict + * when the stack trips a danger state) + * for each guarded state: (sorted by state index) + * state + * alt (the take alternative) + * numDanger (0 when numGuardedStates == 0) + * danger[numDanger] (sorted invoking states whose follow + * epsilon-reaches a guard root: the guard + * defers when the stack carries one) + * numPass + * pass[numPass] (sorted invoking states whose follow + * epsilon-reaches their rule's stop: the + * guard keeps walking the stack past them) + * numPrecedenceDispatches * for each dispatch: (a left-recursive precedence loop decision) * decision * numCutoffs @@ -63,8 +80,10 @@ * their table index.

*/ public class SerializedStaticDFAs extends OutputModelObject { - /** v6: per-table alternative-mask section (prefix-factor groups). */ - public static final int FORMAT_VERSION = 6; + /** v7: per-table guarded-take section (optional-postfix guards). */ + public static final int FORMAT_VERSION = 7; + + private static final int[] NO_INTS = new int[0]; public final int numTables; /** Base64 text segments of the serialized blob, one rendered per line. */ @@ -168,6 +187,25 @@ public static int appendIntStream(Map dfas, } } } + // guarded-take section (v7) + int numGuardedStates = 0; + for (int v : dfa.guardedAlts) { + if (v != 0) numGuardedStates++; + } + data.add(numGuardedStates); + if (numGuardedStates > 0) { + for (int s = 0; s < dfa.numStates; s++) { + if (dfa.guardedAlts[s] == 0) continue; + data.add(s); + data.add(dfa.guardedAlts[s]); + } + } + int[] danger = dfa.guardDanger != null ? dfa.guardDanger : NO_INTS; + int[] pass = dfa.guardPass != null ? dfa.guardPass : NO_INTS; + data.add(danger.length); + for (int v : danger) data.add(v); + data.add(pass.length); + for (int v : pass) data.add(v); int escapes = 0; for (int v : dfa.accepts) { if (v == StaticDFA.ESCAPE) escapes++; @@ -177,7 +215,8 @@ public static int appendIntStream(Map dfas, +": "+(dfa.cyclic ? "LL(*) cyclic" : "LL(k), k="+dfa.maxK) +", "+dfa.numStates+" states" +(escapes > 0 ? ", "+escapes+" adaptive escapes" : "") - +(numMaskStates > 0 ? ", "+numMaskStates+" mask accepts" : "")); + +(numMaskStates > 0 ? ", "+numMaskStates+" mask accepts" : "") + +(numGuardedStates > 0 ? ", "+numGuardedStates+" guarded takes" : "")); } data.add(dispatches.size()); for (int[] entry : dispatches) { @@ -194,7 +233,10 @@ private static int indexOf(List tables, StaticDFA t) { && Arrays.equals(o.acceptMasks, t.acceptMasks) && Arrays.equals(o.fallbacks, t.fallbacks) && Arrays.equals(o.edgeOffsets, t.edgeOffsets) - && Arrays.equals(o.edges, t.edges))) { + && Arrays.equals(o.edges, t.edges) + && Arrays.equals(o.guardedAlts, t.guardedAlts) + && Arrays.equals(o.guardDanger, t.guardDanger) + && Arrays.equals(o.guardPass, t.guardPass))) { return i; } } From e507a660e240e6c95fa39814713c8dbbeddfec8e Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Tue, 28 Jul 2026 10:44:30 -0400 Subject: [PATCH 34/48] Guarded-take: extend to budget escapes and rooted-widened configs Two refinements that close out the remaining take-vetoed escapes, plus a critical emission fix for fully-guarded decisions: - Budget escapes (hybrid depth/state cap) of optional-postfix decisions are now guard candidates: they were never conflict-analyzed, but the guarded-take eligibility check runs on their configuration sets at finalize time just as for conflict escapes (rooted taint and root sets already propagate through them). Bigquery d=309's ten remaining budget escapes - the hot '= (', '= CASE', '= CAST', '= ARRAY' comparison paths - resolve statically now. - The widening bail is relaxed from any-WIDENED to WIDENED-and-not- ROOTED: a widened skip configuration's bottom frame is still a real follow state, so a rooted one's realizability is covered by its recorded guard roots exactly like a non-widened one's; only non-rooted widened configurations remain unguardable. Also adds the missing real-take attestation and skip-foreign checks to the finalize-time eligibility (previously pre-filtered at veto time). - Emission fix: when every escape of a decision resolves to a guarded take, the escape count reaches zero and the hybrid-table emission branch was skipped entirely - the decision silently lost its table (reported CONTEXT_SENSITIVE). The emission gate now also fires on guarded accepts, the candidates carry their conflicting alternative sets through to finalize, and a resolved conflict moves from approx/contextSensitive to exactAmbigConflicts like the factor and descent cures. Census after extension: 1797 guarded takes across six dialects (Duckdb 755, Redshift 420, Databricks 306, Snowflake 272, Bigquery 23, Trino 21). Bigquery d=309 closes fully: escapes=0, coverage=100%. Verification: cargo 12/12 (witness now exercises 13 guard-takes and 18 guard-defers, 1 escape left), tool-testsuite 694/694, runtime-testsuite rust.** 707/707, corpus differentials 3208/dialect - Duckdb 0 mismatches, Trino 2 and Bigquery 3 (all previously proven pre-existing '::' error-path divergences), Rust MERGE/CAST/CASE/unary/parens parity battery 12/12. Perf (Rust, release): Bigquery predicate-heavy queries remain 1.5-2.5x static vs adaptive. Signed-off-by: Bo Lin --- runtime/Rust/tests/gen/guardexprparser.rs | 10 ++-- .../antlr/v4/analysis/DecisionClassifier.java | 49 ++++++++++++++----- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/runtime/Rust/tests/gen/guardexprparser.rs b/runtime/Rust/tests/gen/guardexprparser.rs index fa56ce7e74..8052d596e9 100644 --- a/runtime/Rust/tests/gen/guardexprparser.rs +++ b/runtime/Rust/tests/gen/guardexprparser.rs @@ -1791,7 +1791,7 @@ where // the serialized ATN is followed by 5 static SLL prediction tables (-Xstatic-dfa): // decision 5: precedence-dispatched over cutoffs [1, 2], tables [2 3 4] -// decision 2: LL(*) cyclic, 35 states, 13 adaptive escapes, 1 guarded takes +// decision 2: LL(*) cyclic, 35 states, 6 adaptive escapes, 8 guarded takes // decision 4: LL(k), k=1, 3 states // table 2 (decision 5): LL(k), k=1, 6 states // table 3 (decision 5): LL(k), k=1, 7 states @@ -1810,11 +1810,11 @@ static _serializedATN: [&'static str; 17] = [ "AgAAAFZQAgAAAFheAgAAAFpWAgAAAFpcAgAAAFwKAgAAAF5aAgAAAGBiDgAAAGJwBhAIAGRmChIAAGZo", "ChQAAGhqBggEAGpsChYAAGxwAgAAAG5gAgAAAG5kAgAAAHAOAgAAAHKAAQoYAAB0gAEKGgAAdngKFAAA", "eHoGCAQAenwKFgAAfIABAgAAAH5yAgAAAH50AgAAAH52AgAAAIABEgIAAAAQGjQ+RlZabn4OCgwERuoB", - "AAQABAQCAgQEAAAAAAACAAUABAQCAQEBAQEBAQECAQEBAQEEAAQAAAAAAAAEAgQEBAACAAQAAAAAAAAA", + "AAQABAQCAgQEAAAAAAACAAUABAQCAQEBAQUBAQUCBQUFBQUEAAQAAAAAAAAEAgQEBAACAAQAAAAAAAAA", "AAAAAAAAAAAAAAAqKjw8PDw8PDxOeIoBnAHGAcYB2AHYAeoB6gHqAeoB6gHqAeoB6gHqAeoB6gHqAeoB", "6gHqAeoB6gHqAQEBAgQEBAYGBgoMCA4QChISDBYWDggIEBQUEhgaFAgIFhQUGBgaGgEBHAQEHgYGIAoM", "Ig4QJBISJhYWKAgIKhQUGBgaGggILBQUGBgaLgEBAgQEMAYGBgoMMg4QNBISNhYWOAgIOhQUPBgaPggI", - "QBQUQhgaRAACIAICJAw6PEROVGIIBgwAAgQAAAAADAwMCgoCDAwEAAAAAAEMHgAEBAQCBAQAAAAAAAAe", - "Hh4eHh4BAQIEBAQGBgYKDAgWFgoAAAAAAQ4kAAQEBAIEBAQAAAAAAAAAJCQkJCQkJAEBAgQEBAYGBgoK", - "CAwMChYWDAAAAAABAgAEAAAAAAAAAAIKBAIEBAYI" + "QBQUQhgaRAAQIAIyAjgCPAI+AkACQgJEAgIkDDo8RE5UYggGDAACBAAAAAAMDAwKCgIMDAQAAAAAAQwe", + "AAQEBAIEBAAAAAAAAB4eHh4eHgEBAgQEBAYGBgoMCBYWCgAAAAABDiQABAQEAgQEBAAAAAAAAAAkJCQk", + "JCQkAQECBAQEBgYGCgoIDAwKFhYMAAAAAAECAAQAAAAAAAAAAgoEAgQEBgg=" ]; \ No newline at end of file diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index c89f6f8d48..fa570529ed 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -1223,7 +1223,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List fallbackAlts = new ArrayList(); // 0 = none List stateDepth = new ArrayList(); // lookahead depth (BFS layer) List> ownRoots = new ArrayList>(); // postfix guard roots entering each state - List guardCandidates = new ArrayList(); // take-vetoed conflict states + Map guardCandidates = new LinkedHashMap(); // take-vetoed conflict states -> their conflicting alternatives (null for budget escapes, never conflict-analyzed) this.currentDecisionRule = s.ruleIndex; Set start = new LinkedHashSet(); @@ -1481,7 +1481,7 @@ && hasPendingPrecReturn(c.context)) { // vetoed only by the mirror check: a candidate for // the guarded-take escape (resolved after // construction, once guard roots have propagated) - guardCandidates.add(d); + guardCandidates.put(d, conflicting); } } @@ -1642,6 +1642,13 @@ else if (abortInfAsOverflow) { } else { acceptAlts.set(d, StaticDFA.ESCAPE); + if (currentPostfixShape != null + && alts.cardinality() == 2 && alts.get(1) && alts.get(2)) { + // budget escape of a take/skip state: never conflict- + // analyzed, but the guarded-take escape can still + // resolve it (eligibility is evaluated at finalize) + guardCandidates.put(d, null); + } } } continue; @@ -1732,10 +1739,12 @@ else if (ls.roots != null) { } int escapes = 0; + int guardedCount = 0; for (int a : acceptAlts) { if (a == StaticDFA.ESCAPE) escapes++; + else if (a == StaticDFA.GUARDED) guardedCount++; } - if (escapes > 0) { + if (escapes > 0 || guardedCount > 0) { // hybrid table: emit only if the start state itself resolves // something - a start-state escape means nothing is decidable res.category = Category.HYBRID; @@ -1816,10 +1825,10 @@ protected GuardData finalizeGuardedTakes(DecisionState s, List> edges, List acceptAlts, List acceptMasks, - List> ownRoots, - List guardCandidates, - List guardAlts, - Result res) { + List> ownRoots, + Map guardCandidates, + List guardAlts, + Result res) { int n = states.size(); // propagate guard roots through the edge graph to a fixpoint: // through[s] = own[s] ∪ ∪_{p→s} through[p] @@ -1847,15 +1856,28 @@ else if (rt.addAll(rp)) { Set G = new HashSet(); List guarded = new ArrayList(); - for (int d : guardCandidates) { + for (Map.Entry cand : guardCandidates.entrySet()) { + int d = cand.getKey(); if (acceptAlts.get(d) != StaticDFA.ESCAPE || acceptMasks.get(d) != 0) continue; Set roots = through.get(d); if (roots == null || roots.isEmpty()) continue; boolean eligible = true; + boolean realTake = false; for (ATNConfig c : states.get(d)) { - if (c.alt != 2) continue; int taint = c.reachesIntoOuterContext; - if ((taint & WIDENED_TAINT) != 0) { eligible = false; break; } + if (c.alt == 1 + && (taint & (WIDENED_TAINT|FOREIGN_CONSUME_TAINT)) == 0) { + realTake = true; + } + if (c.alt != 2) continue; + if ((taint & FOREIGN_CONSUME_TAINT) != 0) { eligible = false; break; } + // a widening-born skip configuration is an analysis artifact + // unless it is rooted: then its bottom frame is a real follow + // state and the guard covers its realizability + if ((taint & (WIDENED_TAINT|ROOTED_TAINT)) == WIDENED_TAINT) { + eligible = false; + break; + } if (c.state.ruleIndex == s.ruleIndex) continue; if ((taint & ROOTED_TAINT) != 0) continue; if (bottomFrameIs(c.context, currentPostfixShape.blockEndState, @@ -1866,7 +1888,12 @@ else if (rt.addAll(rp)) { eligible = false; break; } - if (!eligible) continue; + if (!eligible || !realTake) continue; + if (cand.getValue() != null) { + res.approxConflicts.remove(cand.getValue()); + res.contextSensitiveConflicts.remove(cand.getValue()); + res.exactAmbigConflicts.add(cand.getValue()); + } acceptAlts.set(d, StaticDFA.GUARDED); guardAlts.set(d, 1); guarded.add(d); From 9e063f71f29177f24ac730395ea0535ec7c39d17 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Tue, 28 Jul 2026 16:03:30 -0400 Subject: [PATCH 35/48] Chain-descended shared-descent groups: re-admit wrapper-chain factoring (the alias family) cfbed1034 narrowed the member gate so no chain-descended group could form ('re-admitting chain-descended groups soundly is future work'). The selectItem alias family - expression (AS? alias)? vs multiSelect -> selectStar -> primaryExpression DOT ASTERISK - is exactly that shape: both alternatives descend to primaryExpression with zero token consumption, alt1 through expression/booleanExpression/valueExpression wrappers, alt2 through multiSelect/selectStar. The CAND candidates existed but every deep one was vetoed, so e.g. Trino's d=153 kept 133 escape states (its hottest: qualified names, aliases, function calls, subscripts, lambdas, windows). SharedDescentAnalyzer: - firstConsumerUnique generalizes to a wrapper-chain descent verdict (checkDescent): side exits before the body's first R call must be unreachable on the commit region - disjoint from FIRST(R), or, for tokens, preceded by the enclosing block's R-ward alternative (the min-alt rule then keeps the body's first R call aligned with the neutral span; e.g. valueExpression's primaryExpression base beats the MINUS/PLUS unary, which overlaps only on signed numerics). Overlapping side calls (TRIM's trimsSpecification) and R-less completions still veto; Snowflake's CONNECT_BY_ROOT? prefix vetoes d=454 (adaptive prefers the prefix take on the overlap - a genuine misalignment). - The dispatch's tail analysis pops along the recorded descent chain (mandatoryTailChain) instead of grammar-wide pops, which dragged the common rule's own follow positions and sibling members' call sites into the continuation sets (pe's deref DOT and selectStar's DOT arm). The selectItem dispatch is default=1, arms={2:{DOT}}. - The per-config first-consumer proof is re-admitted at both mask- accept sites (allStartViaR), extended for chain-descended groups: V_NOCLEAN inert positions, pre-R positions with approved side exits, post-R positions (wrapper stops, the alias block after the expression invocation), and consumption-based post-first-R exemption. Rust codegen (Rust.stg): - descentMaskPredict: a multi-bit mask no group arm covers now defers to adaptivePredict instead of falling through to an empty default arm. Tables carrying both prefix-factor masks and descent masks (now common) previously produced empty parse bodies on the factor mask states. - copy_from: replace + forget instead of *src = ctx. Assignment drop_in_place's the old value, deallocating the children Vec buffer the new value aliases; with the descent flow that buffer is the arena's most recent allocation (the neutral parse's graft push), so the arena hands it to the body's first Vec push and the decision ctx's subtree is silently replaced (selectItem ended up holding the neutral primaryExpression node instead of the expression wrappers). Verified: Trino Java difftest 1690 checked / 2 known '::' error-path divergences; Rust tree differential corpus 1680/2 (same 2), paren 1200/0, pred 318/0, corpus-err 1 (pre-existing on base2); 12 star/alias smoke cases (T.*, A.B.*, F(A).*, -5, nested subquery stars); cargo 11/11; tool-testsuite 694/0; runtime-testsuite rust.** 707/707; Duckdb static/adaptive corpus pass-fail agreement. Report deltas (escape states): Trino d=153 133 -> 39 (cover 100%); Trino 1263 -> 979; Bigquery 656 -> 546; Duckdb 3726 -> 2742; Redshift 2597 -> 1965. Alias-heavy query (release): 11.6us chain vs 13.4us no-chain static vs 41.0us adaptive. Not covered (sound vetoes or separate shapes): Snowflake d=454 (CONNECT_BY_ROOT overlap), the windowFrame continuation family (wildcard-truncated chains), Databricks pivotAsAlias (optional postfix, not a descent), Databricks LPAREN selectStar RPAREN (fails closed to adaptive). Signed-off-by: Bo Lin --- .../tests/gen/adaptive/betweenexprparser.rs | 54 +- .../tests/gen/adaptive/guardexprparser.rs | 72 ++- .../tests/gen/adaptive/parenexprparser.rs | 99 +++- runtime/Rust/tests/gen/betweenexprparser.rs | 54 +- runtime/Rust/tests/gen/fuzzexprparser.rs | 1 + runtime/Rust/tests/gen/guardexprparser.rs | 72 ++- runtime/Rust/tests/gen/labelsparser.rs | 63 +- runtime/Rust/tests/gen/lrdfaparser.rs | 81 ++- runtime/Rust/tests/gen/parenexprparser.rs | 100 +++- runtime/Rust/tests/gen/staticdfaparser.rs | 63 +- runtime/Rust/tests/gen/visitorcalcparser.rs | 27 +- .../v4/tool/templates/codegen/Rust/Rust.stg | 10 +- .../antlr/v4/analysis/DecisionClassifier.java | 6 +- .../v4/analysis/SharedDescentAnalyzer.java | 542 +++++++++++++++--- 14 files changed, 1077 insertions(+), 167 deletions(-) diff --git a/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs b/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs index 10c0b26f22..429f75e678 100644 --- a/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs @@ -532,7 +532,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; BContextAll::NotContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -625,7 +632,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextExt<'input, ' let tmp = unsafe { std::ptr::read(base_ctx) }; BContextAll::PredicatedContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -718,7 +732,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextExt<'input, 'arena, T let tmp = unsafe { std::ptr::read(base_ctx) }; BContextAll::OrContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -811,7 +832,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; BContextAll::AndContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1132,7 +1160,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; PredContextAll::CmpContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1225,7 +1260,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> BetweenContextExt<'input, 'are let tmp = unsafe { std::ptr::read(base_ctx) }; PredContextAll::BetweenContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/adaptive/guardexprparser.rs b/runtime/Rust/tests/gen/adaptive/guardexprparser.rs index 2195cef06d..cb932acf68 100644 --- a/runtime/Rust/tests/gen/adaptive/guardexprparser.rs +++ b/runtime/Rust/tests/gen/adaptive/guardexprparser.rs @@ -528,7 +528,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> EvalContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; StmtContextAll::EvalContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -621,7 +628,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AssignContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; StmtContextAll::AssignContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -878,7 +892,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::NotContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -971,7 +992,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextExt<'input, ' let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::PredicatedContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1064,7 +1092,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextExt<'input, 'arena, T let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::OrContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1157,7 +1192,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::AndContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1478,7 +1520,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; PredContextAll::CmpContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1567,7 +1616,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> InListContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; PredContextAll::InListContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/adaptive/parenexprparser.rs b/runtime/Rust/tests/gen/adaptive/parenexprparser.rs index 9a97302787..c7dc08f0cf 100644 --- a/runtime/Rust/tests/gen/adaptive/parenexprparser.rs +++ b/runtime/Rust/tests/gen/adaptive/parenexprparser.rs @@ -519,7 +519,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::AddContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -612,7 +619,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ColContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::ColContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -701,7 +715,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ParensContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::ParensContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -790,7 +811,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> SubqueryContextExt<'input, 'ar let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::SubqueryContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -883,7 +911,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> RowConstructorContextExt<'inpu let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::RowConstructorContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -976,7 +1011,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::MulContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1069,7 +1111,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NumContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::NumContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1158,7 +1207,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> UnaryContextExt<'input, 'arena let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::UnaryContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1561,7 +1617,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> SelectContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; QContextAll::SelectContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1650,7 +1713,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NestedContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; QContextAll::NestedContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1743,7 +1813,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> TableContextExt<'input, 'arena let tmp = unsafe { std::ptr::read(base_ctx) }; QContextAll::TableContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index 12fa46c520..20d2789998 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -532,7 +532,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; BContextAll::NotContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -625,7 +632,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextExt<'input, ' let tmp = unsafe { std::ptr::read(base_ctx) }; BContextAll::PredicatedContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -718,7 +732,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextExt<'input, 'arena, T let tmp = unsafe { std::ptr::read(base_ctx) }; BContextAll::OrContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -811,7 +832,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; BContextAll::AndContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut BContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1132,7 +1160,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; PredContextAll::CmpContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1225,7 +1260,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> BetweenContextExt<'input, 'are let tmp = unsafe { std::ptr::read(base_ctx) }; PredContextAll::BetweenContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index af88a052d0..66626de749 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -508,6 +508,7 @@ where } }, x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), m => m, } } { x if x == 0x1 =>{ diff --git a/runtime/Rust/tests/gen/guardexprparser.rs b/runtime/Rust/tests/gen/guardexprparser.rs index 8052d596e9..b3cb3b943d 100644 --- a/runtime/Rust/tests/gen/guardexprparser.rs +++ b/runtime/Rust/tests/gen/guardexprparser.rs @@ -528,7 +528,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> EvalContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; StmtContextAll::EvalContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -621,7 +628,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AssignContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; StmtContextAll::AssignContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut StmtContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -878,7 +892,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NotContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::NotContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -971,7 +992,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PredicatedContextExt<'input, ' let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::PredicatedContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1064,7 +1092,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> OrContextExt<'input, 'arena, T let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::OrContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1157,7 +1192,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AndContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::AndContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1478,7 +1520,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> CmpContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; PredContextAll::CmpContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1567,7 +1616,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> InListContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; PredContextAll::InListContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut PredContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/labelsparser.rs b/runtime/Rust/tests/gen/labelsparser.rs index 22edb68113..7bd3bb3b56 100644 --- a/runtime/Rust/tests/gen/labelsparser.rs +++ b/runtime/Rust/tests/gen/labelsparser.rs @@ -551,7 +551,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::AddContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -644,7 +651,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ParensContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::ParensContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -744,7 +758,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> MultContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::MultContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -837,7 +858,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> DecContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::DecContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -934,7 +962,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AnIDContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::AnIDContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1031,7 +1066,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AnIntContextExt<'input, 'arena let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::AnIntContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1124,7 +1166,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> IncContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::IncContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/lrdfaparser.rs b/runtime/Rust/tests/gen/lrdfaparser.rs index c72aaa518c..8b6cec8339 100644 --- a/runtime/Rust/tests/gen/lrdfaparser.rs +++ b/runtime/Rust/tests/gen/lrdfaparser.rs @@ -533,7 +533,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::AddContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -622,7 +629,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NegContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::NegContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -715,7 +729,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::MulContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -808,7 +829,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> TernaryContextExt<'input, 'are let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::TernaryContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -901,7 +929,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PowContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::PowContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -994,7 +1029,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> IndexContextExt<'input, 'arena let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::IndexContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1087,7 +1129,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> IdContextExt<'input, 'arena, T let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::IdContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1176,7 +1225,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> FactContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::FactContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1269,7 +1325,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> IntContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::IntContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/parenexprparser.rs b/runtime/Rust/tests/gen/parenexprparser.rs index d331ee3624..113321a6e3 100644 --- a/runtime/Rust/tests/gen/parenexprparser.rs +++ b/runtime/Rust/tests/gen/parenexprparser.rs @@ -519,7 +519,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::AddContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -612,7 +619,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ColContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::ColContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -701,7 +715,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ParensContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::ParensContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -790,7 +811,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> SubqueryContextExt<'input, 'ar let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::SubqueryContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -883,7 +911,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> RowConstructorContextExt<'inpu let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::RowConstructorContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -976,7 +1011,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> MulContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::MulContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1069,7 +1111,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NumContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::NumContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1158,7 +1207,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> UnaryContextExt<'input, 'arena let tmp = unsafe { std::ptr::read(base_ctx) }; EContextAll::UnaryContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut EContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1243,6 +1299,7 @@ where } }, x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), + x if (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), m => m, } } { x if x == 0x1 =>{ @@ -1608,7 +1665,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> SelectContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; QContextAll::SelectContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1697,7 +1761,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NestedContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; QContextAll::NestedContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1790,7 +1861,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> TableContextExt<'input, 'arena let tmp = unsafe { std::ptr::read(base_ctx) }; QContextAll::TableContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut QContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index 7309ace0e6..f3808431dc 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -381,7 +381,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> CreateTableContextExt<'input, let tmp = unsafe { std::ptr::read(base_ctx) }; StatContextAll::CreateTableContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -474,7 +481,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> CreateViewContextExt<'input, ' let tmp = unsafe { std::ptr::read(base_ctx) }; StatContextAll::CreateViewContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -567,7 +581,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> DropTableContextExt<'input, 'a let tmp = unsafe { std::ptr::read(base_ctx) }; StatContextAll::DropTableContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut StatContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -836,7 +857,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> CallContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::CallContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -925,7 +953,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> RefContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::RefContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1655,7 +1690,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> DupFirstContextExt<'input, 'ar let tmp = unsafe { std::ptr::read(base_ctx) }; DupContextAll::DupFirstContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut DupContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut DupContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -1740,7 +1782,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> DupSecondContextExt<'input, 'a let tmp = unsafe { std::ptr::read(base_ctx) }; DupContextAll::DupSecondContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut DupContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut DupContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/runtime/Rust/tests/gen/visitorcalcparser.rs b/runtime/Rust/tests/gen/visitorcalcparser.rs index 50277b5853..cef22256ee 100644 --- a/runtime/Rust/tests/gen/visitorcalcparser.rs +++ b/runtime/Rust/tests/gen/visitorcalcparser.rs @@ -527,7 +527,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> AddContextExt<'input, 'arena, let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::AddContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -620,7 +627,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> NumberContextExt<'input, 'aren let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::NumberContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } @@ -729,7 +743,14 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> MultiplyContextExt<'input, 'ar let tmp = unsafe { std::ptr::read(base_ctx) }; ExprContextAll::MultiplyContext(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ExprContextAll<'input, 'arena, Tok>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = >::node_tag(); } diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index 8f969a7b55..6d0b34e187 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -848,6 +848,7 @@ descentMaskPredict(choice, groups) ::= << match _m { 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), + x if (x & (x-1)) != 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), m => m, } } >> @@ -1362,7 +1363,14 @@ impl\<'input: 'arena, 'arena, Tok: Token + 'input> Ext\<'inp let tmp = unsafe { std::ptr::read(base_ctx) }; ContextAll::(tmp.morph(|ext_src| Self::new(ext_src))) }; - *dbt_antlr4::cast_unchecked!(src => mut ContextAll\<'input, 'arena, Tok\>) = ctx; + // replace + forget, NOT assignment: the new value's children Vec + // was moved out of the old one, so dropping the old value would + // deallocate the buffer the new value references (the arena can + // then hand it to another node's Vec - shared-descent resume + // paths hit this: the decision ctx's Vec buffer is the most + // recent arena allocation when copy_from runs). + let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ContextAll\<'input, 'arena, Tok\>), ctx); + std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = \\>::node_tag(); } diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index fa570529ed..f508bb49e4 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -581,7 +581,7 @@ protected boolean allStartViaR(Set configs, DecisionState s, } protected SharedDescentAnalyzer descentAnalyzer() { if (descentAnalyzer == null) { - descentAnalyzer = new SharedDescentAnalyzer(g, atn, callByFollowState()); + descentAnalyzer = new SharedDescentAnalyzer(g, atn); } return descentAnalyzer; } @@ -1551,7 +1551,7 @@ && hasPendingPrecReturn(c.context)) { SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null && System.getProperty("antlr.dfa.disableDescentMasks") == null ? currentDescentPlan.groupCovering(alts) : null; - if (descentGroup != null) { + if (descentGroup != null && allStartViaR(configs, s, descentGroup)) { res.descentMaskStates++; res.approxConflicts.remove(conflicting); res.contextSensitiveConflicts.remove(conflicting); @@ -1632,7 +1632,7 @@ else if (abortInfAsOverflow) { SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null && System.getProperty("antlr.dfa.disableDescentMasks") == null ? currentDescentPlan.groupCovering(alts) : null; - if (descentGroup != null) { + if (descentGroup != null && allStartViaR(configs, s, descentGroup)) { res.descentMaskStates++; acceptMasks.set(d, altBits(alts)); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { diff --git a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java index 2862921da4..87077e7a8c 100644 --- a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java +++ b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java @@ -9,6 +9,8 @@ import org.antlr.v4.runtime.atn.ATN; import org.antlr.v4.runtime.atn.ATNConfig; import org.antlr.v4.runtime.atn.ATNState; +import org.antlr.v4.runtime.atn.BlockEndState; +import org.antlr.v4.runtime.atn.BlockStartState; import org.antlr.v4.runtime.atn.DecisionState; import org.antlr.v4.runtime.atn.PredictionContext; import org.antlr.v4.runtime.atn.RuleStopState; @@ -96,6 +98,12 @@ public Group(int rule, BitSet alts) { * prefix-side boundary of the first-consumer proof (frames * below the R segment are validated only down to these). */ public final Set boundaryStates = new HashSet(); + /** The recorded wrapper call chains of each member alternative + * (outermost call first, the R call last): the dispatch's tail + * analysis pops along these chains - not grammar-wide - so + * phantom returns (R's own follow positions, other members' + * call sites) cannot pollute a member's continuation set. */ + public final Map>> chainsByAlt = new HashMap>>(); } /** Per-decision plan: the shared-descent groups of the decision. */ @@ -117,14 +125,12 @@ public Group groupCovering(BitSet live) { private final Grammar g; private final ATN atn; - private final Map callByFollowState; private final Map> candidateCache = new HashMap>(); private final Map> callSitesCache = new HashMap>(); - public SharedDescentAnalyzer(Grammar g, ATN atn, Map callByFollowState) { + public SharedDescentAnalyzer(Grammar g, ATN atn) { this.g = g; this.atn = atn; - this.callByFollowState = callByFollowState; } /** Build the decision's shared-descent plan. */ @@ -165,6 +171,8 @@ public Plan buildPlan(DecisionState s) { for (AltPath p : paths) { if (grp.callSiteState < 0) grp.callSiteState = p.callSite; grp.boundaryStates.add(p.boundary); + grp.chainsByAlt.computeIfAbsent(p.alt, k -> new ArrayList>()) + .add(p.chain); } analyzeDispatch(s, grp); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { @@ -292,10 +300,14 @@ public static boolean hasDescentMask(Grammar g, int decision) { /** * The dispatch analysis of one group: every member alt's mandatory * continuation after R (its FIRST tokens, FOLLOW tokens included iff - * the continuation is nullable). Explicit arms are the non-nullable - * continuations; the default is the single nullable one. Over- - * approximating (grammar-wide pops, full callee LOOK) can only - * reject sound groups, never accept unsound ones. + * the continuation is nullable), computed by popping along the + * member's recorded descent chain - not grammar-wide - so phantom + * returns (R's own follow positions, other members' call sites) + * cannot pollute the continuation sets. Explicit arms are the + * non-nullable continuations; the default is the single nullable + * one. Over-approximating (full callee LOOK, grammar-wide FOLLOW at + * the decision rule's stop) can only reject sound groups, never + * accept unsound ones. */ private void analyzeDispatch(DecisionState s, Group grp) { LL1Analyzer ll1 = new LL1Analyzer(atn); @@ -303,12 +315,13 @@ private void analyzeDispatch(DecisionState s, Group grp) { Set nullable = new HashSet(); for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { Set nul = new HashSet(); - ATNState start = grp.prefixTokens.isEmpty() - ? s.transition(a-1).target - : postPrefixState(s, a, grp.prefixTokens); - IntervalSet t = start != null - ? mandatoryTailFrom(s, a, grp.rule, ll1, nul, start) - : new IntervalSet(); + IntervalSet t = new IntervalSet(); + List> chains = grp.chainsByAlt.get(a); + if (chains != null) { + for (List chain : chains) { + t.addAll(mandatoryTailChain(s, chain, ll1, nul)); + } + } mandatory.put(a, t); // an empty mandatory tail is a degenerate continuation: the // alternative completes with no discriminating token, so it @@ -344,53 +357,34 @@ private void analyzeDispatch(DecisionState s, Group grp) { } /** - * FIRST tokens of alternative {@code alt}'s mandatory continuation - * after R (over-approximated); {@code nullable} is set when the - * continuation can complete the alternative with no post-R token, - * in which case the decision rule's FOLLOW is included. + * FIRST tokens of the mandatory continuation after R along one + * recorded descent chain (over-approximated by full callee LOOK); + * {@code nullable} is set when the walk reaches the decision rule's + * stop, in which case the decision rule's FOLLOW is included. The + * walk starts at the innermost R-call follow and pops frame by frame + * along the chain (a wrapper rule's stop continues at the next + * outer frame's follow, never grammar-wide). */ - private IntervalSet mandatoryTail(DecisionState s, int alt, int ruleR, LL1Analyzer ll1, - Set nullable) { - return mandatoryTailFrom(s, alt, ruleR, ll1, nullable, s.transition(alt-1).target); - } - - /** Variant of {@link #mandatoryTail} starting from the post-prefix - * state of the alternative (prefix groups: the tail lies after the - * shared prefix tokens). */ - private IntervalSet mandatoryTailFrom(DecisionState s, int alt, int ruleR, LL1Analyzer ll1, - Set nullable, ATNState startState) { + private IntervalSet mandatoryTailChain(DecisionState s, List chain, + LL1Analyzer ll1, Set nullable) { IntervalSet tokens = new IntervalSet(); - Set calls = new HashSet(); Set seen = new HashSet(); Deque work = new ArrayDeque(); - work.add(startState); + work.add(chain.get(chain.size()-1).followState); while (!work.isEmpty()) { - ATNState st = work.poll(); - if (!seen.add(st) || st instanceof RuleStopState) continue; - for (int i = 0; i < st.getNumberOfTransitions(); i++) { - Transition t = st.transition(i); - if (t instanceof RuleTransition) { - if (((RuleTransition)t).target.ruleIndex == ruleR) calls.add(((RuleTransition)t).followState); - else work.add(t.target); + ATNState p = work.poll(); + if (!seen.add(p)) continue; + if (p instanceof RuleStopState) { + int idx = chainFrameOf(chain, p.ruleIndex); + if (idx > 0) { + work.add(chain.get(idx-1).followState); } - else if (t.isEpsilon()) { - work.add(t.target); + else if (p.ruleIndex == s.ruleIndex) { + nullable.add(1); + tokens.addAll(ll1.LOOK(p, null)); } + continue; } - } - for (ATNState follow : calls) { - tailFirst(follow, s.ruleIndex, tokens, nullable, ll1, new HashSet()); - } - return tokens; - } - - private void tailFirst(ATNState st, int decisionRule, IntervalSet tokens, - Set nullable, LL1Analyzer ll1, Set seen) { - Deque work = new ArrayDeque(); - work.add(st); - while (!work.isEmpty()) { - ATNState p = work.poll(); - if (!seen.add(p)) continue; for (int i = 0; i < p.getNumberOfTransitions(); i++) { Transition t = p.transition(i); if (t instanceof RuleTransition) { @@ -398,26 +392,24 @@ private void tailFirst(ATNState st, int decisionRule, IntervalSet tokens, work.add(((RuleTransition)t).followState); } else if (t.isEpsilon()) { - if (p instanceof RuleStopState) { - if (p.ruleIndex == decisionRule) { - nullable.add(1); - tokens.addAll(ll1.LOOK(p, null)); - } - else { - for (RuleTransition rt : callByFollowState.values()) { - if (rt.target.ruleIndex == p.ruleIndex) work.add(rt.followState); - } - } - } - else { - work.add(t.target); - } + work.add(t.target); } - else { + else if (t.label() != null) { tokens.addAll(t.label()); } } } + return tokens; + } + + /** Index of the chain frame whose caller rule is {@code ruleIndex} + * (the frame whose follow state lies in that rule), innermost + * first; -1 when the rule is not a chain caller. */ + private static int chainFrameOf(List chain, int ruleIndex) { + for (int i = chain.size()-1; i >= 0; i--) { + if (chain.get(i).followState.ruleIndex == ruleIndex) return i; + } + return -1; } /** @@ -449,8 +441,162 @@ public boolean startsViaR(ATNConfig c, DecisionState s, int ruleR) { * consumed below it and needs no validation). */ public boolean startsViaR(ATNConfig c, DecisionState s, Group grp) { Set callSites = epsilonCallSites(s, grp); - return segStartsViaR(c.state.ruleIndex, c.context, grp.rule, callSites, grp.boundaryStates, - java.util.Collections.newSetFromMap(new java.util.IdentityHashMap())); + if (segStartsViaR(c.state.ruleIndex, c.context, grp.rule, callSites, grp.boundaryStates, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()))) { + return true; + } + // Chain-descended group, no R segment in the chain. + int v = checkDescent(c.state, grp.rule, + new HashMap(), new HashSet()); + // Inert configuration: the position cannot reach R at all and + // every deviation from it was approved by the member gate's + // side-exit discipline - it can never interact with the descent. + if (v == V_NOCLEAN) return true; + // Post-first-R configuration: reaching the position consumed at + // least one token, so the body's first R call (at the decision + // start, served by the resume) already happened - later R calls + // parse normally. + if (!reachableWithoutConsumption(c.state)) return true; + // A wrapper frame whose invocation is a post-R position (the + // call site is reachable only through an R call) proves the + // config's first-R span already happened, e.g. the selectItem + // alias block, which follows the expression invocation. + if (chainFramesPostR(c.context, grp.rule, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()))) { + return true; + } + // The remaining cases need the wrapper chain below to lie on + // the epsilon descent. + if (!allCallSitesToBoundary(c.context, callSites, grp.boundaryStates, + java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()))) { + return false; + } + // Pre-R configuration: the position still descends to R - on + // the commit region it enters R at a clean call site (the + // member gate's side-exit discipline keeps the body's first R + // call aligned with the neutral span). + if (v != V_VETO) return true; + // Post-R configuration (e.g. a wrapper rule's stop): the + // position is reachable only through an R call, so the config's + // R span already happened - aligned by construction. + return postRPosition(c.state, grp.rule); + } + + /** Any context frame whose call site is a post-R position (the + * site is reachable from its rule's start only through an R + * call): the frame's invocation then happened after the first R + * span, whatever the chain below. */ + private boolean chainFramesPostR(PredictionContext ctx, int ruleR, Set visited) { + if (ctx == null || ctx.isEmpty()) return false; + if (!visited.add(ctx)) return false; + for (int i = 0; i < ctx.size(); i++) { + int rs = ctx.getReturnState(i); + if (rs == PredictionContext.EMPTY_RETURN_STATE) continue; + ATNState site = siteStateByFollow(rs); + if (site != null + && (postRPosition(site, ruleR) || !reachableWithoutConsumption(site))) { + return true; + } + if (chainFramesPostR(ctx.getParent(i), ruleR, visited)) return true; + } + return false; + } + + /** Is {@code state} reachable from its rule's start consuming zero + * tokens? The walk follows epsilon transitions, descends into + * callees, and continues past a callee only when the callee can + * complete token-free (nullable). When it is not, the position + * postdates the body's first R call at the decision start. */ + private boolean reachableWithoutConsumption(ATNState state) { + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + work.add(atn.ruleToStartState[state.ruleIndex]); + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st)) continue; + if (st == state) return true; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + work.add(rt.target); + if (nullableOf(rt.target.ruleIndex)) work.add(rt.followState); + } + else if (t.isEpsilon()) { + work.add(t.target); + } + } + } + return false; + } + + /** Rule nullability (can complete with zero tokens), cached. */ + private final Map ruleNullable = new HashMap(); + private boolean nullableOf(int rule) { + Boolean n = ruleNullable.get(rule); + if (n == null) { + n = new LL1Analyzer(atn).LOOK(atn.ruleToStartState[rule], null) + .contains(org.antlr.v4.runtime.Token.EPSILON); + ruleNullable.put(rule, n); + } + return n; + } + + /** Lazily built: a rule call's follow state number -> the source + * state owning the {@link RuleTransition} (unique calls only; a + * follow shared by multiple call sites maps to no entry). */ + private Map siteStateByFollow; + private ATNState siteStateByFollow(int followState) { + if (siteStateByFollow == null) { + siteStateByFollow = new HashMap(); + Set dup = new HashSet(); + for (ATNState st : atn.states) { + if (st == null) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + int f = ((RuleTransition)t).followState.stateNumber; + if (siteStateByFollow.put(f, st) != null) dup.add(f); + } + } + } + siteStateByFollow.keySet().removeAll(dup); + } + return siteStateByFollow.get(followState); + } + + /** Is {@code state} reachable from its rule's start only through an + * R invocation? The walk explores epsilon and token transitions + * (R-free consumption) and non-R calls (continuing past a callee + * only when it may complete without R - an ALWAYS_R callee called + * R to get there); R calls are barriers. */ + private boolean postRPosition(ATNState state, int ruleR) { + Map memo = new HashMap(); + Set inProgress = new HashSet(); + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + work.add(atn.ruleToStartState[state.ruleIndex]); + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st)) continue; + if (st == state) return false; + if (st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + if (rt.target.ruleIndex == ruleR) continue; // R is a barrier + work.add(rt.target); + if (checkDescent(rt.target, ruleR, memo, inProgress) != V_ALWAYS) { + work.add(rt.followState); + } + } + else { + work.add(t.target); + } + } + } + return true; } /** Does the sub-chain from ({@code stateRule}, {@code ctx}) down @@ -653,14 +799,18 @@ else if (t.isEpsilon()) { */ /** The path of one alternative to R: the leading token sequence * consumed before the (epsilon) descent to R, the R-call's source - * state ({@link #callSite}), and the R-call's follow state + * state ({@link #callSite}), the R-call's follow state * ({@link #boundary} - the prefix-side end of the first-consumer - * proof). */ + * proof), and the full wrapper call chain from the decision + * alternative to the R call (outermost first, the R call last - + * the dispatch analysis pops along it after the neutral parse). */ private static final class AltPath { final List tokens = new ArrayList(); + int alt = -1; int rule = -1; int callSite = -1; int boundary = -1; + final List chain = new ArrayList(); } /** @@ -676,35 +826,41 @@ private static final class AltPath { private List altPaths(DecisionState s, int alt) { List out = new ArrayList(); Deque work = new ArrayDeque(); - work.add(new Object[]{s.transition(alt-1).target, new ArrayList(), Boolean.FALSE}); + work.add(new Object[]{s.transition(alt-1).target, new ArrayList(), Boolean.FALSE, + new ArrayList()}); Set seen = new HashSet(); while (!work.isEmpty()) { Object[] item = work.poll(); ATNState st = (ATNState)item[0]; @SuppressWarnings("unchecked") List tokens = (List)item[1]; boolean inRule = (Boolean)item[2]; + @SuppressWarnings("unchecked") List chain = (List)item[3]; String key = st.stateNumber + "|" + tokens + (inRule ? "r" : ""); if (!seen.add(key) || st instanceof RuleStopState) continue; for (int i = 0; i < st.getNumberOfTransitions(); i++) { Transition t = st.transition(i); if (t instanceof RuleTransition) { RuleTransition rt = (RuleTransition)t; + List nextChain = new ArrayList(chain); + nextChain.add(rt); AltPath p = new AltPath(); + p.alt = alt; p.tokens.addAll(tokens); p.rule = rt.target.ruleIndex; p.callSite = st.stateNumber; p.boundary = rt.followState.stateNumber; + p.chain.addAll(nextChain); out.add(p); - work.add(new Object[]{t.target, tokens, Boolean.TRUE}); + work.add(new Object[]{t.target, tokens, Boolean.TRUE, nextChain}); } else if (t.isEpsilon()) { - work.add(new Object[]{t.target, tokens, inRule}); + work.add(new Object[]{t.target, tokens, inRule, chain}); } else if (!inRule && t.label() != null && tokens.size() < MAX_PREFIX_TOKENS) { for (int tok : t.label().toList()) { List next = new ArrayList(tokens); next.add(tok); - work.add(new Object[]{t.target, next, Boolean.FALSE}); + work.add(new Object[]{t.target, next, Boolean.FALSE, chain}); } } } @@ -712,20 +868,53 @@ else if (!inRule && t.label() != null && tokens.size() < MAX_PREFIX_TOKENS) { return out; } - /** Is R the unique first consuming position of alternative - * {@code alt} after its prefix? The neutral parse invokes R - * immediately after the prefix, so a member alternative's body - * must not be able to consume anything - a token or a non-R call - * - before its first R call, nor to reach the end of the decision - * rule before it. Otherwise the neutral R span and the body's - * first R call can cover different tokens (e.g. {@code TRIM LPAREN - * (trimsSpecification? valueExpression? FROM) ...}, where BOTH is - * a trimsSpecification to the body but identifier content to the - * neutral R) and the resume graft would attach at the wrong - * place. */ + /** Is R the first consuming position of alternative {@code alt} + * after its prefix on every input where a neutral R parse succeeds + * (the descent block's commit region)? The walk descends from the + * post-prefix start through epsilon transitions and wrapper-rule + * calls; an R call ends a path successfully. Every side exit - a + * token or a non-R call that would let the body consume (or + * complete) before its first R call - must be unreachable on the + * commit region: + * + *
    + *
  • a side token disjoint from FIRST(R) is never consumed when + * the neutral R parse succeeds;
  • + *
  • a side call whose FIRST is disjoint from FIRST(R)'s + * likewise;
  • + *
  • an overlapping side token is still never taken when the + * enclosing block's R-ward alternative precedes it: both are + * viable on the commit region, so adaptivePredict's min-alt + * rule picks the R-ward one (e.g. valueExpression's + * primaryExpression base alternative beats the MINUS/PLUS + * unary alternatives, which overlap FIRST(primaryExpression) + * only on signed numerics);
  • + *
  • everything else - an overlapping side call, an R-less + * completion, an overlapping token without R-ward priority - + * mis-aligns the body's first R call from the neutral parse's + * span and vetoes the member (cf. the TRIM from-form family: + * BOTH starts both trimsSpecification and a valueExpression, + * so the neutral parse can consume as R content a token the + * body consumes before its first R call). + *
+ * + * With {@code -Dantlr.dfa.disableChainDescent=1} the walk reverts + * to the shallow discipline (no wrapper descent: every token, non-R + * call, or rule end before R vetoes). */ private boolean firstConsumerUnique(DecisionState s, int alt, AltPath p) { ATNState start = postPrefixState(s, alt, p.tokens); if (start == null) return false; + if (System.getProperty("antlr.dfa.disableChainDescent") != null) { + return firstConsumerUniqueShallow(start, p.rule); + } + return checkDescent(start, p.rule, + new HashMap(), new HashSet()) == V_ALWAYS; + } + + /** The pre-chain-descent member gate: every epsilon path from + * {@code start} must reach an R call before any token, any non-R + * call, or the rule end. */ + private boolean firstConsumerUniqueShallow(ATNState start, int ruleR) { Set seen = new HashSet(); Deque work = new ArrayDeque(); work.add(start); @@ -737,7 +926,7 @@ private boolean firstConsumerUnique(DecisionState s, int alt, AltPath p) { for (int i = 0; i < st.getNumberOfTransitions(); i++) { Transition t = st.transition(i); if (t instanceof RuleTransition) { - if (((RuleTransition)t).target.ruleIndex != p.rule) return false; + if (((RuleTransition)t).target.ruleIndex != ruleR) return false; any = true; } else if (t.isEpsilon()) { @@ -751,6 +940,185 @@ else if (t.isEpsilon()) { return any; } + /** Descent verdicts of {@link #checkDescent}. */ + private static final int V_VETO = 0; + private static final int V_ALWAYS = 1; + private static final int V_SOMETIMES = 2; + private static final int V_NOCLEAN = 3; + + /** Verdict of the descent from {@code start} (a state inside one + * rule body, no consumption so far) to the body's first R call: + * V_ALWAYS when every path that survives the side-exit checks calls + * R before completing, V_SOMETIMES when R is called on some path + * but a survivable R-less completion also exists, V_NOCLEAN when no + * clean path to R exists but every side exit was approved (the + * position is unreachable on the commit region - exempt, not a + * veto), V_VETO when a side exit can be taken on the commit region. + * Memoized per (R, start state); genuine recursion on the clean + * descent vetoes (conservative). */ + private int checkDescent(ATNState start, int ruleR, + Map memo, Set inProgress) { + Long mkey = (((long)ruleR) << 32) | start.stateNumber; + Integer m = memo.get(mkey); + if (m != null) return m; + if (!inProgress.add(mkey)) return V_VETO; + IntervalSet firstR = firstOfRule(ruleR); + boolean foundR = false; + boolean rLess = false; + boolean veto = false; + Set seen = new HashSet(); + Deque work = new ArrayDeque(); + work.add(start); + while (!work.isEmpty() && !veto) { + ATNState st = work.poll(); + if (!seen.add(st)) continue; + if (st instanceof RuleStopState) { rLess = true; continue; } + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + int callee = rt.target.ruleIndex; + if (callee == ruleR) { foundR = true; continue; } + if (firstOfRule(callee).and(firstR).isNil()) continue; // disjoint side call + int v = checkDescent(rt.target, ruleR, memo, inProgress); + if (v == V_VETO) { veto = true; break; } + foundR = true; + if (v == V_SOMETIMES) work.add(rt.followState); + } + else if (t.isEpsilon()) { + work.add(t.target); + } + else if (t.label() == null) { + work.add(t.target); // actions: no token consumption + } + else if (t.label().and(firstR).isNil()) { + continue; // disjoint side token + } + else if (!tokenPriority(st, ruleR)) { + veto = true; + } + } + } + inProgress.remove(mkey); + int v = veto ? V_VETO : !foundR ? V_NOCLEAN : (rLess ? V_SOMETIMES : V_ALWAYS); + memo.put(mkey, v); + return v; + } + + /** FIRST set of a rule (epsilon stripped), cached. */ + private final Map ruleFirst = new HashMap(); + private IntervalSet firstOfRule(int rule) { + IntervalSet f = ruleFirst.get(rule); + if (f == null) { + f = new LL1Analyzer(atn).LOOK(atn.ruleToStartState[rule], null); + f.remove(org.antlr.v4.runtime.Token.EPSILON); + ruleFirst.put(rule, f); + } + return f; + } + + /** Min-alt priority for an overlapping side token at {@code st}: + * the innermost block enclosing the token must have an R-ward + * alternative (reaching R with zero token consumption) preceding + * the token's alternative; on the commit region both are viable + * and adaptivePredict's min-alt rule then takes the R-ward one, + * keeping the body's first R call aligned with the neutral span. */ + private boolean tokenPriority(ATNState st, int ruleR) { + Long ba = enclosingAlt(st); + if (ba == null) return false; + int blk = (int)(ba >> 32); + int altIdx = (int)(ba & 0xffffffffL); + ATNState bs = atn.states.get(blk); + if (!(bs instanceof BlockStartState)) return false; + int clean = cleanAltOfBlock((BlockStartState)bs, ruleR); + return clean != 0 && clean < altIdx; + } + + /** Minimum alternative index of block {@code b} through which R is + * reachable with zero token consumption, or 0 when none. */ + private int cleanAltOfBlock(BlockStartState b, int ruleR) { + for (int i = 0; i < b.getNumberOfTransitions(); i++) { + if (reachesRuleEpsilon(b.transition(i).target, ruleR, new HashSet())) { + return i + 1; + } + } + return 0; + } + + /** Can R be reached from {@code start} following epsilon + * transitions and rule calls (descending into callees and + * continuing past their returns) with zero token consumption? */ + private boolean reachesRuleEpsilon(ATNState start, int ruleR, Set seen) { + Deque work = new ArrayDeque(); + work.add(start); + while (!work.isEmpty()) { + ATNState st = work.poll(); + if (!seen.add(st) || st instanceof RuleStopState) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition) { + RuleTransition rt = (RuleTransition)t; + if (rt.target.ruleIndex == ruleR) return true; + work.add(rt.target); + work.add(rt.followState); + } + else if (t.isEpsilon()) { + work.add(t.target); + } + } + } + return false; + } + + /** Innermost enclosing (BlockStartState state number, alternative + * index) pair per ATN state, packed into a long; states outside + * any block have no entry. */ + private final Map> blockAltCache = new HashMap>(); + private Long enclosingAlt(ATNState st) { + Map m = blockAltCache.get(st.ruleIndex); + if (m == null) { + m = computeEnclosingAlts(st.ruleIndex); + blockAltCache.put(st.ruleIndex, m); + } + return m.get(st); + } + + /** One stack-carrying DFS over a rule's own states, recording the + * innermost (block, alt) of every state. */ + private Map computeEnclosingAlts(int rule) { + Map m = new HashMap(); + Deque work = new ArrayDeque(); + work.add(new Object[]{atn.ruleToStartState[rule], new ArrayList()}); + Set seen = new HashSet(); + while (!work.isEmpty()) { + Object[] it = work.poll(); + ATNState st = (ATNState)it[0]; + @SuppressWarnings("unchecked") List stack = (List)it[1]; + if (!seen.add(st)) continue; + if (!stack.isEmpty()) m.put(st, stack.get(stack.size()-1)); + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof RuleTransition || !t.isEpsilon()) continue; // intra-rule only + List next = stack; + if (st instanceof BlockStartState) { + next = new ArrayList(stack); + next.add(((long)st.stateNumber << 32) | (i + 1)); + } + else if (st instanceof BlockEndState) { + if (!stack.isEmpty()) { + next = new ArrayList(stack); + next.remove(next.size()-1); + } + } + work.add(new Object[]{t.target, next}); + } + } + return m; + } + + /** Can R be reached from {@code start} following epsilon + * transitions and rule calls only (zero tokens)? */ + /** Can R be reached from {@code start} following epsilon * transitions and rule calls only (zero tokens)? */ private boolean descendsToR(ATNState start, int ruleR, Set seen) { From fa0e09c894554d5da84c5800dda1787ca231f477 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Tue, 28 Jul 2026 23:39:21 -0400 Subject: [PATCH 36/48] Shared-descent dispatch: real-stack follow guard, conditional members, FIRST pre-check Three shared-descent extensions that close the identifier/keyword fanout family of hybrid escapes (the 'primaryExpression widened' hotspot: fat depth-2 budget escapes where functionCall/measure/lambda/columnRef all descend through the same identifier chain), plus the ordering rule that keeps the analysis and the generated dispatch code in agreement. 1. Guarded tail dispatch (the boundary-collision family). The plan-time dispatch proof required explicit tail arms disjoint from a nullable member's grammar-wide FOLLOW - hopeless in these grammars, where every alias position accepts every keyword, so the identifier groups never got arms. Worse, the default arm's 'viable set' never actually contained the rule's FOLLOW (LOOK(stop, null) yields only epsilon), so single-nullable groups passed the collision check unsoundly - 'F(A, 2)' committed columnLambdaExpr on the arg-list comma on ClickHouse. mandatoryTailChain now chases the stop's grammar-wide follow links for the default set, and groups that fail the check get guarded arms instead: arm = the member's in-decision tail FIRST set minus every other member's, committing only when the real parse stack's postfix chase cannot consume the dispatch token. The chase (BaseParser.follow_contains) walks the actual context frames against per-invocation-site continuation sets - context-free fixpoints over the ATN computed lazily once per grammar (follow_sets.rs), exact where the static analysis only had the chase-wide boundary approximation. Commits are then sound: every other member is dead on that token, and a dying arm alternative is the accepted error-path class. 2. Conditional members with head guards. firstConsumerUnique vetoes any member whose body can consume before its first shared-rule call - which excluded functionCall (its optional processingMode head) from the identifier groups, the single hottest escape shape ('x ('). The gate now collects the side exits' gating tokens instead: on lookahead outside the set no pre-R consumption is possible, so the neutral span is aligned; on lookahead inside, the block defers to adaptivePredict. altPaths also continues past nullable wrappers, so the candidate chains through functionCallHead/functionName form at all. Per alternative, a clean chain erases conditional ones (their distinct frames fail the mask-time per-config proof); the group's head guard is the union of what remains. Trino d=316: 52 -> 14 escape states; corpus escapes 1191 -> 959 (the remaining are the alias and SUBSTRING families, where the dispatch would defer anyway). 3. FIRST(R) pre-check. The neutral parse is attempted only when the post-prefix lookahead can start the shared rule - a doomed attempt costs an errorful muted parse (16x regression on plain TRIM(x), where the neutral trimsSpecification always fails; now 2.6us vs 2.3us adaptive). 4. Dispatch ordering and consistent pairing. Conditional admission made a head-guarded primaryExpression group shadow the unconditional strictNonReserved group at the alias family's selectItem decisions (Databricks d=289/292/464/421, Snowflake d=454 flipped EXACT_AMBIG -> HYBRID, ~+400 escape states): first-match covering won while its first-consumer proof failed on the paren-lambda configs. Plans now order unconditional (head-guard-free) groups before conditional ones, and mask acceptance picks exactly the group the generated code would fire - the first codegenable group covering the mask - and accepts only when THAT group passes the proof, so a mask's runtime arm is never unproven. When no codegenable group covers, any proven group accepts (the runtime has no arm to fire and defers). All five decisions restored: Databricks 2732 (-88 vs baseline), Snowflake 2012 (-183). Also: begin_neutral_parse fetches the resume position before seeking (the walk buffers only the lookahead it consumed; prefix>=2 groups resumed one past the buffered range and hit the stream's seek panic). Verification: cargo 57/0 (regen'd witnesses), tool-testsuite 694/0, runtime-testsuite rust.** 707/707; static-vs-adaptive tree diffs: Trino 2880/2 (known :: error-path class), Snowflake 2880/0, Databricks 2880/0, Duckdb 2880/0, Bigquery 2880/3 (same class), ClickHouse 1680/1 (error-path recovery shape on invalid input); Trino Rust twins corpus 1680/2, paren 1200/0, pred 318/0, err 10/0. Perf: SELECT A + F(A,2) X 3.3us vs 6.2us adaptive; A.*, B.C 2.3us vs 5.6us; corpus 73ms vs 90ms. Signed-off-by: Bo Lin --- runtime/Rust/src/atn.rs | 11 + runtime/Rust/src/follow_sets.rs | 190 +++++++++++++++ runtime/Rust/src/lib.rs | 1 + runtime/Rust/src/parser.rs | 36 +++ runtime/Rust/tests/gen/fuzzexprparser.rs | 152 +++++++++++- runtime/Rust/tests/gen/parenexprparser.rs | 10 +- .../v4/tool/templates/codegen/Rust/Rust.stg | 8 +- .../antlr/v4/analysis/DecisionClassifier.java | 46 +++- .../v4/analysis/SharedDescentAnalyzer.java | 219 ++++++++++++++++-- .../org/antlr/v4/codegen/ParserFactory.java | 14 +- .../antlr/v4/codegen/model/DescentGroup.java | 17 +- 11 files changed, 660 insertions(+), 44 deletions(-) create mode 100644 runtime/Rust/src/follow_sets.rs diff --git a/runtime/Rust/src/atn.rs b/runtime/Rust/src/atn.rs index 03dd8aac18..ea63214afd 100644 --- a/runtime/Rust/src/atn.rs +++ b/runtime/Rust/src/atn.rs @@ -49,6 +49,11 @@ pub struct ATN { /// [`crate::static_dfa`]. pub static_dfas: StaticDFATables, + /// Real-stack postfix-chase continuation sets for the guarded + /// shared-descent dispatch, computed on first use (see + /// [`crate::follow_sets`]). + follow_sets: std::sync::OnceLock, + states: Vec>>, } @@ -76,6 +81,7 @@ impl ATN { rule_to_stop_state: Vec::new(), rule_to_token_type: Vec::new(), static_dfas: StaticDFATables::empty(), + follow_sets: std::sync::OnceLock::new(), states: Vec::new(), } } @@ -110,6 +116,11 @@ impl ATN { *self.get_state_mut(state_number) = state; } + /// The invocation-site continuation sets (lazily computed). + pub fn follow_sets(&self) -> &crate::follow_sets::FollowSets { + crate::follow_sets::FollowSets::of(&self.follow_sets, self) + } + pub(crate) fn alloc_states(&mut self, count: usize) { self.states .resize_with(self.states.len() + count, || Box::pin(ATNState::default())); diff --git a/runtime/Rust/src/follow_sets.rs b/runtime/Rust/src/follow_sets.rs new file mode 100644 index 0000000000..f9976aeaaf --- /dev/null +++ b/runtime/Rust/src/follow_sets.rs @@ -0,0 +1,190 @@ +//! Real-stack postfix-chase FIRST sets for the guarded descent dispatch +//! (`-Xstatic-dfa` shared-descent groups with a nullable member). +//! +//! A shared-descent group's tail dispatch commits to a member alternative on +//! the post-R lookahead token. When the group has a member that can complete +//! right after the shared rule (a *nullable* member, e.g. a bare column +//! reference), the commit is sound only when that member is dead on the real +//! parse stack - i.e. when the dispatch token cannot follow the decision +//! rule on this stack. The static analysis can only answer that with the +//! grammar-wide FOLLOW set, which is far too coarse (every alias position +//! accepts every keyword). The dispatch therefore evaluates the *real* +//! postfix chase: walking the parser's actual context frames, the token can +//! follow iff it starts the continuation of some frame's rule body (and +//! every frame below it completes token-free). +//! +//! This module precomputes, lazily and once per ATN, for every rule +//! invocation site the FIRST set of the caller-body continuation from the +//! call's follow position to the rule end (`first`), and whether that +//! continuation can complete token-free (`nullable`). Both are plain +//! context-free fixpoints over the ATN (no widening, no recursion cut), so +//! the chase is exact: `first` is a superset of the true continuation set +//! (a predicate could only narrow it), which is the sound direction - the +//! chase may defer a commit it could have taken, never take one it must +//! not. + +use std::sync::OnceLock; + +use crate::atn::ATN; +use crate::token::TOKEN_EPSILON; +use crate::transition::TransitionType; + +/// Per invocation-site continuation sets (see module docs). Indexed by +/// call-site ATN state number; unpopulated slots are (empty, false). +pub struct FollowSets { + /// Bitset over token types (`TOKEN_EOF` = -1 is never included) of the + /// continuation's FIRST tokens, one row per call-site state. + first: Vec>, + /// Whether the continuation from the call's follow position can reach + /// the rule's end consuming no token. + nullable: Vec, +} + +fn set_bit(words: &mut [u64], token: i32) -> bool { + let old = (words[token as usize / 64] >> (token as usize % 64)) & 1; + words[token as usize / 64] |= 1 << (token as usize % 64); + old == 0 +} + +impl FollowSets { + /// The continuation sets of every invocation site of the grammar, + /// computed on first use. + pub fn of<'a>(cell: &'a OnceLock, atn: &ATN) -> &'a FollowSets { + cell.get_or_init(|| Self::compute(atn)) + } + + /// Compute the continuation sets for every invocation site. + fn compute(atn: &ATN) -> FollowSets { + let n_states = atn.states_count(); + let max_token = atn.max_token_type; + let words = (max_token as usize + 64) / 64; + + // Per-state fixpoint: first(s) = FIRST of the language from s to + // its rule's end; nullable(s) = the language contains epsilon. + // Transitions contribute: + // token label l: first += l + // epsilon: first += first(target), nullable |= nullable(target) + // call C with follow f: first += FIRST(C); if nullable(C) { + // first += first(f); nullable |= nullable(f) } + let mut first: Vec> = vec![vec![0; words]; n_states]; + let mut nullable: Vec = vec![false; n_states]; + let mut changed = true; + while changed { + changed = false; + for s in 0..n_states { + let mut acc: Option> = None; + let mut acc_nullable = false; + for tr in atn.get_state(s as i32).get_transitions() { + let target = tr.get_target().get_state_number() as usize; + let acc = acc.get_or_insert_with(|| first[s].clone()); + match tr.transition_type() { + TransitionType::Atom | TransitionType::Set | TransitionType::Range => { + if let Some(label) = tr.get_label() { + for iv in label { + for tok in iv.a..=iv.b.min(max_token) { + if tok >= crate::token::TOKEN_MIN_USER_TOKEN_TYPE && set_bit(acc, tok) { + changed = true; + } + } + } + } + } + TransitionType::NotSet => { + if let Some(label) = tr.get_label() { + for tok in 1..=max_token { + if !label.contains(tok) && set_bit(acc, tok) { + changed = true; + } + } + } + } + TransitionType::Wildcard => { + for tok in 1..=max_token { + if set_bit(acc, tok) { + changed = true; + } + } + } + TransitionType::Rule => { + let rule_tr = tr.try_as::().unwrap(); + let follow = rule_tr.follow_state.get_state_number() as usize; + for w in 0..words { + let add = first[target][w] & !acc[w]; + if add != 0 { + acc[w] |= add; + changed = true; + } + } + if nullable[target] { + for w in 0..words { + let add = first[follow][w] & !acc[w]; + if add != 0 { + acc[w] |= add; + changed = true; + } + } + if nullable[follow] && !acc_nullable { + acc_nullable = true; + changed = true; + } + } + } + _ => { + // epsilon, action, predicate, precedence + // predicate (evaluated as epsilon here - the + // superset direction, sound for the guard) + for w in 0..words { + let add = first[target][w] & !acc[w]; + if add != 0 { + acc[w] |= add; + changed = true; + } + } + if nullable[target] && !acc_nullable { + acc_nullable = true; + changed = true; + } + } + } + } + if let Some(a) = acc { + first[s] = a; + if acc_nullable { + nullable[s] = true; + } + } + } + } + + let mut site_first: Vec> = vec![Vec::new(); n_states]; + let mut site_nullable = vec![false; n_states]; + for s in 0..n_states { + for tr in atn.get_state(s as i32).get_transitions() { + if matches!(tr.transition_type(), TransitionType::Rule) { + let rule_tr = tr.try_as::().unwrap(); + let follow = rule_tr.follow_state.get_state_number() as usize; + site_first[s] = first[follow].clone(); + site_nullable[s] = nullable[follow]; + } + } + } + FollowSets { first: site_first, nullable: site_nullable } + } + + /// Does the continuation after the invocation at call-site `state` + /// start with `token`? (Empty row = not a call site: nothing follows.) + #[inline] + pub fn contains(&self, state: usize, token: i32) -> bool { + state < self.first.len() + && !self.first[state].is_empty() + && token >= 0 + && (self.first[state][token as usize / 64] >> (token as usize % 64)) & 1 != 0 + } + + /// Can the continuation after the invocation at call-site `state` + /// complete token-free? + #[inline] + pub fn nullable(&self, state: usize) -> bool { + state < self.nullable.len() && self.nullable[state] + } +} diff --git a/runtime/Rust/src/lib.rs b/runtime/Rust/src/lib.rs index b82cf29fa4..3ead8a282e 100644 --- a/runtime/Rust/src/lib.rs +++ b/runtime/Rust/src/lib.rs @@ -91,6 +91,7 @@ pub mod atn; pub mod atn_config_set; #[doc(hidden)] pub mod atn_deserializer; +pub mod follow_sets; pub mod common_token_stream; pub mod error_listener; pub mod error_strategy; diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index d18ecca43c..9a1edcfc2c 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -557,6 +557,37 @@ where self.dfa_walk(decision) } + /// The real-stack postfix chase of the guarded descent dispatch (see + /// [`crate::follow_sets`]): can `token` follow the decision rule on + /// the current parse stack? Walking the context frames upward, the + /// token follows iff it starts the caller-body continuation of some + /// frame and every frame below completes token-free. A shared-descent + /// group's tail dispatch commits to an explicit member on the dispatch + /// token only when this returns false (the group's nullable member, + /// e.g. a bare column reference, is then dead on this stack). + pub fn follow_contains(&self, token: i32) -> bool { + let sets = self.atn_manager.atn().follow_sets(); + let mut c = self.ctx(); + while let Some(node) = c { + let inv = node.get_invoking_state(); + if inv < 0 { + break; + } + if std::env::var_os("DBG_FOLLOW").is_some() { + eprintln!("FOLLOW token={} inv={} contains={} nullable={}", + token, inv, sets.contains(inv as usize, token), sets.nullable(inv as usize)); + } + if sets.contains(inv as usize, token) { + return true; + } + if !sets.nullable(inv as usize) { + return false; + } + c = node.get_parent(); + } + token == crate::token::TOKEN_EOF + } + /// Set the stage for a neutral prefix parse: /// - Mark the input stream so it can be rewound later /// - Skip over prefix tokens (note: do NOT parse them through @@ -586,6 +617,11 @@ where let pos0 = self.input.index(); let mark = self.input.mark(); let ctx = self.ctx(); + // the DFA walk buffered only the lookahead it consumed; the + // neutral parse resumes prefix_len tokens ahead, which can sit + // one past the buffered range - fetch it before seeking (the + // stream's seek panics on an unbuffered index) + self.input.la(prefix_len + 1); self.input.seek(pos0 + prefix_len); self.muted += 1; diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index 66626de749..1774575b22 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -463,7 +463,7 @@ where match { let _m = recog.base.dfa_predict_mask(2)?; match _m { 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() => { + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_T__6 | FuzzExpr_T__11 | FuzzExpr_ID | FuzzExpr_INT].contains(&recog.input.la(1)) => { recog.base.set_state(25); let _neutral_state = recog.base.begin_neutral_parse(0); match recog.e() { @@ -488,10 +488,10 @@ where // resume mode; anything else rewinds and defers to the // adaptive engine from the decision start - no resume, // the chosen body re-parses everything - let _tailbit = match recog.input.la(1) { - FuzzExpr_T__2 => Some(0x1), + let _tailbit = { let _t = recog.input.la(1); match _t { + FuzzExpr_T__2 if !false || !recog.base.follow_contains(_t) => Some(0x1), _ => Some(0x2), - }; + } }; match _tailbit { Some(bit) => { recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e); @@ -508,6 +508,141 @@ where } }, x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_T__11 | FuzzExpr_ID | FuzzExpr_INT].contains(&recog.input.la(1)) => { + recog.base.set_state(45); + let _neutral_state = recog.base.begin_neutral_parse(0); + match recog.atom() { + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, + Err(_) => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything + let _tailbit = { let _t = recog.input.la(1); match _t { + FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), + _ => None, + } }; + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_atom); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + } + } + }, + } + }, + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_ID].contains(&recog.input.la(1)) => { + recog.base.set_state(67); + let _neutral_state = recog.base.begin_neutral_parse(0); + match recog.q() { + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, + Err(_) => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything + let _tailbit = { let _t = recog.input.la(1); match _t { + FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), + _ => None, + } }; + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_q); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + } + } + }, + } + }, + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_ID].contains(&recog.input.la(1)) => { + recog.base.set_state(34); + let _neutral_state = recog.base.begin_neutral_parse(0); + match recog.name() { + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, + Err(_) => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything + let _tailbit = { let _t = recog.input.la(1); match _t { + FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), + _ => None, + } }; + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_name); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + } + } + }, + } + }, + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), x if (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), m => m, } } { @@ -629,6 +764,9 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn name(&mut self,) -> Result<&'arena NameContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + if let Some(_node) = self.base.resume_take(RULE_name)? { + return Ok(_node.as_rule_context().unwrap()); + } dbt_antlr4::maybe_grow_stack!({ let recog = self; let _parentctx = recog.base.take_ctx(); @@ -743,6 +881,9 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn q(&mut self,) -> Result<&'arena QContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + if let Some(_node) = self.base.resume_take(RULE_q)? { + return Ok(_node.as_rule_context().unwrap()); + } dbt_antlr4::maybe_grow_stack!({ let recog = self; let _parentctx = recog.base.take_ctx(); @@ -1136,6 +1277,9 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn atom(&mut self,) -> Result<&'arena AtomContextAll<'input, 'arena, TF::Tok>, ANTLRError> { + if let Some(_node) = self.base.resume_take(RULE_atom)? { + return Ok(_node.as_rule_context().unwrap()); + } dbt_antlr4::maybe_grow_stack!({ let recog = self; let _parentctx = recog.base.take_ctx(); diff --git a/runtime/Rust/tests/gen/parenexprparser.rs b/runtime/Rust/tests/gen/parenexprparser.rs index 113321a6e3..5c84c016ec 100644 --- a/runtime/Rust/tests/gen/parenexprparser.rs +++ b/runtime/Rust/tests/gen/parenexprparser.rs @@ -1253,7 +1253,7 @@ where match { let _m = recog.base.dfa_predict_mask(1)?; match _m { 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), - x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() => { + x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [ParenExpr_T__0 | ParenExpr_T__3 | ParenExpr_ID | ParenExpr_INT].contains(&recog.input.la(2)) => { recog.base.set_state(13); let _neutral_state = recog.base.begin_neutral_parse(1); match recog.e() { @@ -1278,11 +1278,11 @@ where // resume mode; anything else rewinds and defers to the // adaptive engine from the decision start - no resume, // the chosen body re-parses everything - let _tailbit = match recog.input.la(1) { - ParenExpr_T__1 => Some(0x4), - ParenExpr_T__2 => Some(0x8), + let _tailbit = { let _t = recog.input.la(1); match _t { + ParenExpr_T__1 if !false || !recog.base.follow_contains(_t) => Some(0x4), + ParenExpr_T__2 if !false || !recog.base.follow_contains(_t) => Some(0x8), _ => None, - }; + } }; match _tailbit { Some(bit) => { recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e); diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index 6d0b34e187..205ba1146a 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -854,7 +854,7 @@ descentMaskPredict(choice, groups) ::= << >> DescentGroup(g, tails) ::= << - x if x != 0 && (x & !) == 0 && (x & (x-1)) != 0 && !.base.resume_active() => { + x if x != 0 && (x & !) == 0 && (x & (x-1)) != 0 && !.base.resume_active() && && => { .base.set_state(); let _neutral_state = .base.begin_neutral_parse(); match .() { @@ -879,10 +879,10 @@ DescentGroup(g, tails) ::= << // resume mode; anything else rewinds and defers to the // adaptive engine from the decision start - no resume, // the chosen body re-parses everything - let _tailbit = match .input.la(1) { + let _tailbit = { let _t = .input.la(1); match _t { _ => Some()None, - }; + } }; match _tailbit { Some(bit) => { .base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_); @@ -901,7 +901,7 @@ DescentGroup(g, tails) ::= << x if x != 0 && (x & !) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), >> -Tail(t) ::= " => Some()," +Tail(t) ::= " if ! || !.base.follow_contains(_t) => Some()," // Resume-mode short-circuit at the top of a resume-target rule: when a // shared-descent re-descent reaches the common rule, return the stored diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index f508bb49e4..1d7bc97bf2 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -555,6 +555,30 @@ public Result(DecisionState decisionState) { /** The shared-descent plan of the decision being classified. */ protected SharedDescentAnalyzer.Plan currentDescentPlan; + /** The group a mask-accept dispatches through, chosen so the + * analysis and the generated code agree: the generated arms fire + * the FIRST codegenable group covering the mask (later groups only + * when its runtime guards trip), so the mask is accepted exactly + * when that group passes the first-consumer proof. When no + * codegenable group covers, any proven group will do - the runtime + * has no arm to fire and defers to adaptivePredict, which needs no + * dispatch proof of its own. */ + protected SharedDescentAnalyzer.Group pickDescentGroup( + java.util.List covering, Set configs, + DecisionState s) { + boolean anyCodegenable = false; + for (SharedDescentAnalyzer.Group cand : covering) { + if (!cand.codegenable) continue; + anyCodegenable = true; + return allStartViaR(configs, s, cand) ? cand : null; + } + if (anyCodegenable) return null; + for (SharedDescentAnalyzer.Group cand : covering) { + if (allStartViaR(configs, s, cand)) return cand; + } + return null; + } + /** Do all live configurations of this state genuinely start via the * group's rule (first-consumer proof, prefix-aware)? Configurations * of non-member alternatives are exempt: they fall through to the @@ -1548,10 +1572,13 @@ && hasPendingPrecReturn(c.context)) { acceptMasks.set(d, altBits(factorGroup.alts)); } else { - SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null - && System.getProperty("antlr.dfa.disableDescentMasks") == null - ? currentDescentPlan.groupCovering(alts) : null; - if (descentGroup != null && allStartViaR(configs, s, descentGroup)) { + SharedDescentAnalyzer.Group descentGroup = null; + if (currentDescentPlan != null + && System.getProperty("antlr.dfa.disableDescentMasks") == null) { + descentGroup = pickDescentGroup( + currentDescentPlan.groupsCovering(alts), configs, s); + } + if (descentGroup != null) { res.descentMaskStates++; res.approxConflicts.remove(conflicting); res.contextSensitiveConflicts.remove(conflicting); @@ -1629,10 +1656,13 @@ else if (abortInfAsOverflow) { acceptMasks.set(d, altBits(factorGroup.alts)); } else { - SharedDescentAnalyzer.Group descentGroup = currentDescentPlan != null - && System.getProperty("antlr.dfa.disableDescentMasks") == null - ? currentDescentPlan.groupCovering(alts) : null; - if (descentGroup != null && allStartViaR(configs, s, descentGroup)) { + SharedDescentAnalyzer.Group descentGroup = null; + if (currentDescentPlan != null + && System.getProperty("antlr.dfa.disableDescentMasks") == null) { + descentGroup = pickDescentGroup( + currentDescentPlan.groupsCovering(alts), configs, s); + } + if (descentGroup != null) { res.descentMaskStates++; acceptMasks.set(d, altBits(alts)); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { diff --git a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java index 87077e7a8c..872e8e17ec 100644 --- a/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java +++ b/tool/src/org/antlr/v4/analysis/SharedDescentAnalyzer.java @@ -71,6 +71,42 @@ public static class Group { * pairwise-disjoint explicit arms (each disjoint from the * default's viable set). */ public boolean codegenable; + /** Per-member mandatory tail FIRST sets (the post-R continuation + * along the recorded chains), retained when the plan-time dispatch + * proof fails so the post-construction pass can finalize arms + * against the table's observed boundary continuations (see + * {@link #armsDeferred}). */ + public final Map mandatoryTail = new HashMap(); + /** Members whose continuation after R can complete (they may + * complete right after R - the boundary members); retained for + * the deferred-arms pass. */ + public final BitSet nullableMembers = new BitSet(); + /** Per-member in-decision tail FIRST sets (the continuation after R + * along the recorded chains, WITHOUT the decision-rule FOLLOW + * union): the guarded dispatch subtracts these among members; the + * FOLLOW part is the runtime guard's business. */ + public final Map tailFirst = new HashMap(); + /** The dispatch arms are guarded (see {@link #armsDeferred}-class + * groups): an explicit arm commits only when the real parse stack's + * postfix chase cannot consume the dispatch token, so a live + * nullable member on the real stack defers to adaptivePredict. */ + public boolean guardedDispatch; + /** Head-guard tokens of the group's conditional members: a member + * whose body can consume before its first R call only through a + * side exit starting with one of these tokens (e.g. a function + * call's optional processing mode before the function name). On + * lookahead NOT in this set every member's first R call is the + * first consumed token, so the neutral R span is aligned; on + * lookahead in this set the block defers to adaptivePredict. */ + public final IntervalSet headGuard = new IntervalSet(); + /** FIRST set of the shared rule: the neutral parse is attempted + * only when the post-prefix lookahead can start R at all (a doomed + * attempt costs an errorful muted parse before the defer). */ + public final IntervalSet firstTokens = new IntervalSet(); + /** The plan-time dispatch proof failed (an explicit arm collided + * with a nullable member's grammar-wide FOLLOW, or several + * members are nullable): arms are computed guarded instead. */ + public boolean armsDeferred; public Group(int rule, BitSet alts) { this.rule = rule; @@ -121,6 +157,21 @@ public Group groupCovering(BitSet live) { } return null; } + + /** Every group whose block alternatives cover {@code live}: the + * mask acceptance must try each in turn - a group whose + * first-consumer proof fails on the state's configurations must + * not shadow a later group that covers the same alternatives and + * would pass. */ + public List groupsCovering(BitSet live) { + List out = new ArrayList(); + for (Group grp : groups) { + BitSet covered = (BitSet)(grp.blockAlts.isEmpty() ? grp.alts.clone() : grp.blockAlts.clone()); + covered.and(live); + if (covered.equals(live)) out.add(grp); + } + return out; + } } private final Grammar g; @@ -157,22 +208,47 @@ public Plan buildPlan(DecisionState s) { } continue; } + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("CAND-OK d=%d alt=%d rule=%s prefix=%s head=%s%n", s.decision, a, + g.getRule(p.rule).name, p.tokens, p.headTokens); + } String key = p.rule + "|" + p.tokens; byKey.computeIfAbsent(key, k -> new BitSet()).set(a); pathsByKey.computeIfAbsent(key, k -> new ArrayList()).add(p); } } for (Map.Entry e : byKey.entrySet()) { + if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("CLUSTER d=%d key=%s alts=%s%n", s.decision, e.getKey(), e.getValue()); + } if (e.getValue().cardinality() < 2) continue; List paths = pathsByKey.get(e.getKey()); AltPath first = paths.get(0); Group grp = new Group(first.rule, e.getValue()); grp.prefixTokens.addAll(first.tokens); + grp.firstTokens.addAll(firstOfRule(grp.rule)); + // per member alternative: a clean chain (no side exits before + // the first R call) proves unconditional membership and erases + // the alternative's conditional chains (their distinct frames + // fail the mask-time per-config proof); only when every chain + // is conditional does the alternative join the head guard + Map> pathsByAlt = new LinkedHashMap>(); for (AltPath p : paths) { - if (grp.callSiteState < 0) grp.callSiteState = p.callSite; - grp.boundaryStates.add(p.boundary); - grp.chainsByAlt.computeIfAbsent(p.alt, k -> new ArrayList>()) - .add(p.chain); + pathsByAlt.computeIfAbsent(p.alt, k -> new ArrayList()).add(p); + } + for (List perAlt : pathsByAlt.values()) { + List use = new ArrayList(); + for (AltPath p : perAlt) { + if (p.headTokens.isNil()) use.add(p); + } + if (use.isEmpty()) use = perAlt; + for (AltPath p : use) { + if (grp.callSiteState < 0) grp.callSiteState = p.callSite; + grp.boundaryStates.add(p.boundary); + grp.headGuard.addAll(p.headTokens); + grp.chainsByAlt.computeIfAbsent(p.alt, k -> new ArrayList>()) + .add(p.chain); + } } analyzeDispatch(s, grp); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { @@ -196,6 +272,11 @@ public Plan buildPlan(DecisionState s) { s.decision, g.getRule(grp.rule).name, grp.prefixTokens, grp.alts, grp.defaultAlt, grp.explicitArms); } } + // Order groups with unconditional (head-guard-free) members first: + // a conditional group defers on its guard tokens and is the weaker + // dispatch, so the mask acceptance and the generated arms (which + // must agree on the firing order) try unconditional groups first. + plan.groups.sort((x, y) -> Boolean.compare(!x.headGuard.isNil(), !y.headGuard.isNil())); return plan; } @@ -316,19 +397,23 @@ private void analyzeDispatch(DecisionState s, Group grp) { for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { Set nul = new HashSet(); IntervalSet t = new IntervalSet(); + IntervalSet tailOnly = new IntervalSet(); List> chains = grp.chainsByAlt.get(a); if (chains != null) { for (List chain : chains) { - t.addAll(mandatoryTailChain(s, chain, ll1, nul)); + t.addAll(mandatoryTailChain(s, chain, ll1, nul, tailOnly)); } } mandatory.put(a, t); + grp.tailFirst.put(a, tailOnly); // an empty mandatory tail is a degenerate continuation: the // alternative completes with no discriminating token, so it // belongs to the default arm, not an explicit one if (!nul.isEmpty() || t.isNil()) nullable.add(a); } - if (nullable.size() > 1) return; + grp.mandatoryTail.putAll(mandatory); + for (int a : nullable) grp.nullableMembers.set(a); + if (nullable.size() > 1) { deferArms(s, grp); return; } IntervalSet defaultSet = nullable.isEmpty() ? new IntervalSet() : mandatory.get(nullable.iterator().next()); IntervalSet acc = new IntervalSet(); @@ -336,11 +421,11 @@ private void analyzeDispatch(DecisionState s, Group grp) { if (nullable.contains(a)) continue; IntervalSet t = mandatory.get(a); for (int tok : t.toArray()) { - if (acc.contains(tok)) return; + if (acc.contains(tok)) { deferArms(s, grp); return; } acc.add(tok); } for (int tok : defaultSet.toArray()) { - if (t.contains(tok)) return; + if (t.contains(tok)) { deferArms(s, grp); return; } } } if (!nullable.isEmpty()) grp.defaultAlt = nullable.iterator().next(); @@ -356,6 +441,44 @@ private void analyzeDispatch(DecisionState s, Group grp) { grp.codegenable = grp.defaultAlt != 0 || anyTokens; } + /** Mark the group's dispatch as guarded (see {@link Group#guardedDispatch}): + * the plan-time proof failed against a nullable member's + * grammar-wide FOLLOW, so the tail dispatch arms commit only when + * the real parse stack's postfix chase cannot consume the dispatch + * token (evaluated at runtime). Arms are the members' in-decision + * tail FIRST sets minus every other member's; the nullable + * members' grammar-wide continuations are the guard's business, + * not the arms'. */ + private void deferArms(DecisionState s, Group grp) { + boolean any = false; + for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { + IntervalSet others = new IntervalSet(); + for (int y = grp.alts.nextSetBit(0); y >= 0; y = grp.alts.nextSetBit(y+1)) { + if (y != a) others.addAll(grp.tailFirst.get(y)); + } + IntervalSet arm = IntervalSet.subtract(grp.tailFirst.get(a), others); + if (!arm.isNil()) { + grp.explicitArms.put(a, arm); + any = true; + } + } + // no default commit: every unclaimed token defers to the + // adaptive engine through the widen arm + grp.defaultAlt = 0; + grp.armsDeferred = false; + grp.guardedDispatch = any; + grp.codegenable = any; + if (any && "descent".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("ARMS-GUARDED d=%d rule=%s alts=%s arms=%s nullable=%s%n", + s.decision, g.getRule(grp.rule).name, grp.alts, grp.explicitArms, + grp.nullableMembers); + for (int a = grp.alts.nextSetBit(0); a >= 0; a = grp.alts.nextSetBit(a+1)) { + System.err.printf(" TAILFIRST d=%d alt=%d %s%n", + s.decision, a, grp.tailFirst.get(a).toString(g.getVocabulary())); + } + } + } + /** * FIRST tokens of the mandatory continuation after R along one * recorded descent chain (over-approximated by full callee LOOK); @@ -366,7 +489,8 @@ private void analyzeDispatch(DecisionState s, Group grp) { * outer frame's follow, never grammar-wide). */ private IntervalSet mandatoryTailChain(DecisionState s, List chain, - LL1Analyzer ll1, Set nullable) { + LL1Analyzer ll1, Set nullable, + IntervalSet tailOnly) { IntervalSet tokens = new IntervalSet(); Set seen = new HashSet(); Deque work = new ArrayDeque(); @@ -381,7 +505,15 @@ private IntervalSet mandatoryTailChain(DecisionState s, List cha } else if (p.ruleIndex == s.ruleIndex) { nullable.add(1); - tokens.addAll(ll1.LOOK(p, null)); + // the decision rule's FOLLOW: the tool's stop states carry + // grammar-wide follow links; LOOK(p, null) itself yields + // only epsilon at a stop, so chase them explicitly (the + // default arm's viable set must be grammar-wide for the + // dispatch's collision check to be sound) + for (int i = 0; i < p.getNumberOfTransitions(); i++) { + Transition t = p.transition(i); + if (t.isEpsilon()) tokens.addAll(ll1.LOOK(t.target, null)); + } } continue; } @@ -389,6 +521,7 @@ else if (p.ruleIndex == s.ruleIndex) { Transition t = p.transition(i); if (t instanceof RuleTransition) { tokens.addAll(ll1.LOOK(t.target, null)); + tailOnly.addAll(ll1.LOOK(t.target, null)); work.add(((RuleTransition)t).followState); } else if (t.isEpsilon()) { @@ -396,6 +529,7 @@ else if (t.isEpsilon()) { } else if (t.label() != null) { tokens.addAll(t.label()); + tailOnly.addAll(t.label()); } } } @@ -447,7 +581,7 @@ public boolean startsViaR(ATNConfig c, DecisionState s, Group grp) { } // Chain-descended group, no R segment in the chain. int v = checkDescent(c.state, grp.rule, - new HashMap(), new HashSet()); + new HashMap(), new HashSet(), null); // Inert configuration: the position cannot reach R at all and // every deviation from it was approved by the member gate's // side-exit discipline - it can never interact with the descent. @@ -587,7 +721,7 @@ private boolean postRPosition(ATNState state, int ruleR) { RuleTransition rt = (RuleTransition)t; if (rt.target.ruleIndex == ruleR) continue; // R is a barrier work.add(rt.target); - if (checkDescent(rt.target, ruleR, memo, inProgress) != V_ALWAYS) { + if (checkDescent(rt.target, ruleR, memo, inProgress, null) != V_ALWAYS) { work.add(rt.followState); } } @@ -811,6 +945,9 @@ private static final class AltPath { int callSite = -1; int boundary = -1; final List chain = new ArrayList(); + /** Side-exit tokens gating the body's first R call (conditional + * membership; see Group#headGuard). */ + final IntervalSet headTokens = new IntervalSet(); } /** @@ -852,6 +989,12 @@ private List altPaths(DecisionState s, int alt) { p.chain.addAll(nextChain); out.add(p); work.add(new Object[]{t.target, tokens, Boolean.TRUE, nextChain}); + if (nullableOf(rt.target.ruleIndex)) { + // a nullable wrapper completes token-free: the descent + // continues past it (e.g. a function call's optional + // processing-mode head before the function name) + work.add(new Object[]{rt.followState, tokens, inRule, chain}); + } } else if (t.isEpsilon()) { work.add(new Object[]{t.target, tokens, inRule, chain}); @@ -908,7 +1051,7 @@ private boolean firstConsumerUnique(DecisionState s, int alt, AltPath p) { return firstConsumerUniqueShallow(start, p.rule); } return checkDescent(start, p.rule, - new HashMap(), new HashSet()) == V_ALWAYS; + new HashMap(), new HashSet(), p.headTokens) == V_ALWAYS; } /** The pre-chain-descent member gate: every epsilon path from @@ -956,11 +1099,35 @@ else if (t.isEpsilon()) { * veto), V_VETO when a side exit can be taken on the commit region. * Memoized per (R, start state); genuine recursion on the clean * descent vetoes (conservative). */ + /** Verdict of the descent from {@code start} (a state inside one + * rule body, no consumption so far) to the body's first R call: + * V_ALWAYS when every path that survives the side-exit checks calls + * R before completing, V_SOMETIMES when R is called on some path + * but a survivable R-less completion also exists, V_NOCLEAN when no + * clean path to R exists but every side exit was approved (the + * position is unreachable on the commit region - exempt, not a + * veto), V_VETO when a side exit can be taken on the commit region. + * Memoized per (R, start state); genuine recursion on the clean + * descent vetoes (conservative). + * + *

When {@code headTokens} is non-null the walk runs in + * collecting mode (the member gate's conditional + * admission): instead of vetoing, an overlapping side token without + * R-ward priority and a callee whose own descent vetoes are gated + * into {@code headTokens} - on lookahead outside the set no pre-R + * consumption can happen (the side token is not it, and a gated + * callee cannot start), so the body's first R call is the first + * consumed token. A callee that cannot reach R at all (V_NOCLEAN - + * inert on the commit region) is treated as a nullable wrapper: the + * R path past it is explored. */ private int checkDescent(ATNState start, int ruleR, - Map memo, Set inProgress) { + Map memo, Set inProgress, + IntervalSet headTokens) { Long mkey = (((long)ruleR) << 32) | start.stateNumber; - Integer m = memo.get(mkey); - if (m != null) return m; + if (headTokens == null) { + Integer m = memo.get(mkey); + if (m != null) return m; + } if (!inProgress.add(mkey)) return V_VETO; IntervalSet firstR = firstOfRule(ruleR); boolean foundR = false; @@ -980,10 +1147,19 @@ private int checkDescent(ATNState start, int ruleR, int callee = rt.target.ruleIndex; if (callee == ruleR) { foundR = true; continue; } if (firstOfRule(callee).and(firstR).isNil()) continue; // disjoint side call - int v = checkDescent(rt.target, ruleR, memo, inProgress); - if (v == V_VETO) { veto = true; break; } + int v = checkDescent(rt.target, ruleR, memo, inProgress, headTokens); + if (v == V_VETO) { + if (headTokens != null) { + // the callee's internal veto is unreachable without + // entering it, and entering consumes a FIRST(callee) + // token first - gate the whole call on it + headTokens.addAll(firstOfRule(callee)); + continue; + } + veto = true; break; + } foundR = true; - if (v == V_SOMETIMES) work.add(rt.followState); + if (v == V_SOMETIMES || v == V_NOCLEAN) work.add(rt.followState); } else if (t.isEpsilon()) { work.add(t.target); @@ -995,13 +1171,14 @@ else if (t.label().and(firstR).isNil()) { continue; // disjoint side token } else if (!tokenPriority(st, ruleR)) { - veto = true; + if (headTokens != null) headTokens.addAll(t.label()); + else veto = true; } } } inProgress.remove(mkey); int v = veto ? V_VETO : !foundR ? V_NOCLEAN : (rLess ? V_SOMETIMES : V_ALWAYS); - memo.put(mkey, v); + if (headTokens == null) memo.put(mkey, v); return v; } diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index 472575cd84..4c5c87d3d7 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -334,6 +334,17 @@ protected org.antlr.v4.codegen.model.DescentAltBlock buildDescentAltBlock( gen.getTarget().escapeIfNeeded(g.getRule(grp.rule).name), defaultBit, grp.callSiteState); group.prefixLen = grp.prefixTokens.size(); + if (!grp.headGuard.isNil()) { + // the guard inspects the first token after the shared prefix: + // a conditional member's pre-R side exits live there, not at + // the decision start + group.headGuard = "![" + tailArmKey(grp.headGuard) + "].contains(&recog.input.la(" + + (grp.prefixTokens.size()+1) + "))"; + } + if (!grp.firstTokens.isNil()) { + group.firstCheck = "[" + tailArmKey(grp.firstTokens) + "].contains(&recog.input.la(" + + (grp.prefixTokens.size()+1) + "))"; + } for (int t : grp.prefixTokens) { group.prefixTokens.add( g.name + '_' + gen.getTarget().escapeIfNeeded( @@ -342,7 +353,8 @@ protected org.antlr.v4.codegen.model.DescentAltBlock buildDescentAltBlock( for (java.util.Map.Entry e : grp.explicitArms.entrySet()) { group.tails.add(new org.antlr.v4.codegen.model.DescentGroup.Tail( - this, tailArmKey(e.getValue()), e.getKey())); + this, tailArmKey(e.getValue()), e.getKey(), + grp.guardedDispatch && !grp.nullableMembers.isEmpty())); } block.groups.add(group); any = true; diff --git a/tool/src/org/antlr/v4/codegen/model/DescentGroup.java b/tool/src/org/antlr/v4/codegen/model/DescentGroup.java index 1cd26ad9c7..72d9e438be 100644 --- a/tool/src/org/antlr/v4/codegen/model/DescentGroup.java +++ b/tool/src/org/antlr/v4/codegen/model/DescentGroup.java @@ -24,11 +24,16 @@ public class DescentGroup extends OutputModelObject { public static class Tail extends OutputModelObject { public final String armKey; public final String altBit; + /** Guarded arm: commits only when the real parse stack's postfix + * chase cannot consume the dispatch token (the group's nullable + * member is then dead on this stack). */ + public final boolean guarded; - public Tail(OutputModelFactory factory, String armKey, int alt) { + public Tail(OutputModelFactory factory, String armKey, int alt, boolean guarded) { super(factory); this.armKey = armKey; this.altBit = "0x" + Long.toHexString(1L << (alt-1)); + this.guarded = guarded; } } @@ -51,6 +56,16 @@ public Tail(OutputModelFactory factory, String armKey, int alt) { /** The default member's singleton bit (hex literal), or null for an * all-explicit dispatch (the fallback widens via adaptivePredict). */ public final String defaultBit; + /** Head-guard check of a group with conditional members (see + * SharedDescentAnalyzer.Group#headGuard): rendered as a boolean + * expression that is false when the lookahead enters a member's + * pre-R side exit (the neutral span would misalign); null when the + * group has no conditional members. */ + public String headGuard; + /** FIRST(R) pre-check (see SharedDescentAnalyzer.Group#firstTokens): + * the neutral parse is attempted only when the post-prefix + * lookahead can start R. */ + public String firstCheck; public DescentGroup(OutputModelFactory factory, int decision, long cover, String ruleName, String defaultBit, int callSiteState) { From 1fafa0894334352c4b1b74ac90366e073d9818b4 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Wed, 29 Jul 2026 11:55:57 -0400 Subject: [PATCH 37/48] Bump version to 2.0.2 Signed-off-by: Bo Lin --- antlr4-maven-plugin/pom.xml | 2 +- pom.xml | 2 +- runtime-testsuite/pom.xml | 2 +- runtime/Java/pom.xml | 2 +- runtime/Rust/Cargo.toml | 2 +- runtime/Rust/gen_test_grammars.sh | 2 +- tool-testsuite/pom.xml | 2 +- tool/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/antlr4-maven-plugin/pom.xml b/antlr4-maven-plugin/pom.xml index a40dbb9adf..f015891d86 100644 --- a/antlr4-maven-plugin/pom.xml +++ b/antlr4-maven-plugin/pom.xml @@ -8,7 +8,7 @@ org.antlr antlr4-master - 2.0.1 + 2.0.2 antlr4-maven-plugin maven-plugin diff --git a/pom.xml b/pom.xml index b913d9a98d..edf9ce595c 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ org.antlr antlr4-master - 2.0.1 + 2.0.2 pom ANTLR 4 diff --git a/runtime-testsuite/pom.xml b/runtime-testsuite/pom.xml index 93af0df9e3..2d8b736a9b 100644 --- a/runtime-testsuite/pom.xml +++ b/runtime-testsuite/pom.xml @@ -10,7 +10,7 @@ org.antlr antlr4-master - 2.0.1 + 2.0.2 antlr4-runtime-testsuite ANTLR 4 Runtime Tests (4th generation) diff --git a/runtime/Java/pom.xml b/runtime/Java/pom.xml index f0e673add4..02881e93c3 100644 --- a/runtime/Java/pom.xml +++ b/runtime/Java/pom.xml @@ -9,7 +9,7 @@ org.antlr antlr4-master - 2.0.1 + 2.0.2 ../../pom.xml antlr4-runtime diff --git a/runtime/Rust/Cargo.toml b/runtime/Rust/Cargo.toml index 8787a63e5d..0d975b7a86 100644 --- a/runtime/Rust/Cargo.toml +++ b/runtime/Rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dbt-antlr4" -version = "2.0.1" +version = "2.0.2" authors = ["Konstantin Anisimov ", "Alex Snaps ", "Bo Lin "] homepage = "https://github.com/sdf-labs/antlr4" repository = "https://github.com/sdf-labs/antlr4" diff --git a/runtime/Rust/gen_test_grammars.sh b/runtime/Rust/gen_test_grammars.sh index 47439c456a..31f954b92b 100755 --- a/runtime/Rust/gen_test_grammars.sh +++ b/runtime/Rust/gen_test_grammars.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -TOOL_VERSION="2.0.1" +TOOL_VERSION="2.0.2" ANTLR_PATH="../../../tool/target/dbt-antlr4-${TOOL_VERSION}-complete.jar" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" diff --git a/tool-testsuite/pom.xml b/tool-testsuite/pom.xml index ec887bc17b..83799c11a7 100644 --- a/tool-testsuite/pom.xml +++ b/tool-testsuite/pom.xml @@ -10,7 +10,7 @@ org.antlr antlr4-master - 2.0.1 + 2.0.2 antlr4-tool-testsuite ANTLR 4 Tool Tests diff --git a/tool/pom.xml b/tool/pom.xml index bb2d8cdf2e..ba2736ce5b 100644 --- a/tool/pom.xml +++ b/tool/pom.xml @@ -9,7 +9,7 @@ org.antlr antlr4-master - 2.0.1 + 2.0.2 antlr4 ANTLR 4 Tool From 264b0a5437f40fafe1d2dce75ba9bb8e44f0055a Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Wed, 29 Jul 2026 12:53:59 -0400 Subject: [PATCH 38/48] Slim down generated Rust code Move per-rule boilerplate from the codegen template into runtime macros: - impl_ctx!: context type alias, extension struct, create() and the CustomRuleContext impl (plain/labeled/alt-label arms) - parse_rule!: rule-body scaffolding (enter_rule/exit_rule, error recovery, stack-growth guard; rec/catch variants) - impl_parser_recog!/impl_lexer_recog!: ParserRecog/LexerRecog/Actions impls including sempred/action dispatch - dbt_antlr4::prelude: single glob import replacing the per-file import wall Generated parser files shrink ~28% (tests/gen: 18638 -> 13479 lines); CSV parser 700 -> 414 lines. Verified with cargo test (default and all features) and the rust runtime-testsuite (707 tests, 0 failures). Signed-off-by: Bo Lin --- runtime/Rust/Cargo.lock | 2 +- runtime/Rust/src/lib.rs | 595 +++++++ runtime/Rust/src/prelude.rs | 41 + .../tests/gen/adaptive/betweenexprlexer.rs | 41 +- .../tests/gen/adaptive/betweenexprparser.rs | 1147 ++++---------- .../Rust/tests/gen/adaptive/fuzzexprlexer.rs | 41 +- .../Rust/tests/gen/adaptive/fuzzexprparser.rs | 1002 ++++-------- .../Rust/tests/gen/adaptive/guardexprlexer.rs | 41 +- .../tests/gen/adaptive/guardexprparser.rs | 1100 +++---------- .../Rust/tests/gen/adaptive/parenexprlexer.rs | 41 +- .../tests/gen/adaptive/parenexprparser.rs | 1058 +++---------- runtime/Rust/tests/gen/betweenexprlexer.rs | 41 +- runtime/Rust/tests/gen/betweenexprparser.rs | 1147 ++++---------- runtime/Rust/tests/gen/csvlexer.rs | 41 +- runtime/Rust/tests/gen/csvparser.rs | 463 ++---- runtime/Rust/tests/gen/fuzzexprlexer.rs | 41 +- runtime/Rust/tests/gen/fuzzexprparser.rs | 1370 ++++++----------- runtime/Rust/tests/gen/guardexprlexer.rs | 41 +- runtime/Rust/tests/gen/guardexprparser.rs | 1100 +++---------- runtime/Rust/tests/gen/labelslexer.rs | 41 +- runtime/Rust/tests/gen/labelsparser.rs | 858 +++-------- runtime/Rust/tests/gen/lrdfalexer.rs | 41 +- runtime/Rust/tests/gen/lrdfaparser.rs | 894 +++-------- runtime/Rust/tests/gen/parenexprlexer.rs | 41 +- runtime/Rust/tests/gen/parenexprparser.rs | 1152 ++++---------- runtime/Rust/tests/gen/referencetoatnlexer.rs | 41 +- .../Rust/tests/gen/referencetoatnparser.rs | 180 +-- runtime/Rust/tests/gen/simplelrlexer.rs | 41 +- runtime/Rust/tests/gen/simplelrparser.rs | 268 +--- runtime/Rust/tests/gen/staticdfalexer.rs | 41 +- runtime/Rust/tests/gen/staticdfaparser.rs | 1140 +++----------- runtime/Rust/tests/gen/visitorbasiclexer.rs | 41 +- runtime/Rust/tests/gen/visitorbasicparser.rs | 126 +- runtime/Rust/tests/gen/visitorcalclexer.rs | 41 +- runtime/Rust/tests/gen/visitorcalcparser.rs | 466 ++---- runtime/Rust/tests/gen/xmllexer.rs | 53 +- .../v4/tool/templates/codegen/Rust/Rust.stg | 263 +--- 37 files changed, 4029 insertions(+), 11052 deletions(-) create mode 100644 runtime/Rust/src/prelude.rs diff --git a/runtime/Rust/Cargo.lock b/runtime/Rust/Cargo.lock index 8b34e291c8..bcb5f55f49 100644 --- a/runtime/Rust/Cargo.lock +++ b/runtime/Rust/Cargo.lock @@ -71,7 +71,7 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "dbt-antlr4" -version = "2.0.1" +version = "2.0.2" dependencies = [ "bit-set", "bumpalo", diff --git a/runtime/Rust/src/lib.rs b/runtime/Rust/src/lib.rs index 3ead8a282e..04a3773412 100644 --- a/runtime/Rust/src/lib.rs +++ b/runtime/Rust/src/lib.rs @@ -114,6 +114,7 @@ mod atn_type; // mod context_factory; pub mod rule_context; pub mod vocabulary; +pub mod prelude; // ======= Re-exports ======== #[cfg(feature = "stacker")] @@ -834,3 +835,597 @@ macro_rules! cast_unchecked { unsafe { &mut *ptr } }}; } + +/// Generates the boilerplate for a grammar rule's context extension type. +/// +/// Full form (field-less plain contexts) emits the context type alias, the +/// extension struct, its `create` constructor and the `CustomRuleContext` +/// impl. The `@plain`/`@labeled`/`@alt` arms emit only the +/// `CustomRuleContext` impl for contexts whose struct and constructor the +/// generated code declares itself (labeled fields, rule arguments, +/// `contextSuperClass`, or labeled alternatives). +#[macro_export] +macro_rules! impl_ctx { + // Field-less plain rule context: alias + extension struct + `create` + // + `CustomRuleContext` impl. + ($nodekind:ident, $ctx:ident, $ext:ident, $rule:expr) => { + pub type $ctx<'input, 'arena, Tok = $crate::token::CommonToken<'input>> = + $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + $ext<'input, 'arena, Tok>, + $nodekind, + Tok, + >; + + #[derive(Debug)] + pub struct $ext<'input: 'arena, 'arena, Tok: $crate::token::Token + 'input = $crate::token::CommonToken<'input>> { + ph: ::std::marker::PhantomData<(&'arena (), &'input Tok)>, + } + + impl<'input: 'arena, 'arena, Tok: $crate::token::Token + 'input> $ext<'input, 'arena, Tok> { + fn create( + arena: &'arena $crate::Arena, + parent: ::std::option::Option< + &'arena $crate::tree::TreeNode<'input, 'arena, $nodekind, Tok>, + >, + invoking_state: i32, + ) -> ::std::result::Result< + &'arena mut $crate::tree::TreeNode<'input, 'arena, $nodekind, Tok>, + $crate::errors::ANTLRError, + > { + $crate::parser_rule_context::BaseParserRuleContext::create( + arena, + parent, + invoking_state, + $ext { + ph: ::std::marker::PhantomData, + }, + ) + } + } + + $crate::impl_ctx!(@plain $nodekind::$ctx, $ext, $rule); + }; + + // `CustomRuleContext` impl for a plain node payload (`alloc_zeroed_node`). + (@plain $nodekind:ident::$variant:ident, $ext:ident, $rule:expr) => { + impl<'input: 'arena, 'arena, Tok> $crate::rule_context::CustomRuleContext<'input, 'arena, Tok> + for $ext<'input, 'arena, Tok> + where + Tok: $crate::token::Token + 'input, + { + type NodeKind = $nodekind; + + fn node_tag() -> $nodekind { + $nodekind::$variant + } + + fn get_rule_index(&self) -> usize { + $rule + } + + fn make_node( + arena: &'arena $crate::Arena, + ctx: $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + ) -> *mut $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok> { + arena.alloc_zeroed_node(ctx) + } + + fn cast_from<'a>( + node: &'a $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok>, + ) -> ::std::option::Option< + &'a $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + > { + if node.node_tag() + == >::node_tag() + { + ::std::option::Option::Some($crate::cast_unchecked!(node.ctx_ptr() => $crate::parser_rule_context::BaseParserRuleContext<'input, 'arena, Self, Self::NodeKind, Tok>)) + } else { + ::std::option::Option::None + } + } + + fn cast_from_mut<'a>( + node: &'a mut $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok>, + ) -> ::std::option::Option< + &'a mut $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + > { + if node.node_tag() + == >::node_tag() + { + ::std::option::Option::Some($crate::cast_unchecked!(node.ctx_ptr() => mut $crate::parser_rule_context::BaseParserRuleContext<'input, 'arena, Self, Self::NodeKind, Tok>)) + } else { + ::std::option::Option::None + } + } + } + }; + + // `CustomRuleContext` impl for the base context of a rule with labeled + // alternatives: the node payload is the `ContextAll` enum and fresh + // nodes start as its `Error` variant. + (@labeled $nodekind:ident::$variant:ident, $ctxall:ident, $ext:ident, $rule:expr) => { + impl<'input: 'arena, 'arena, Tok> $crate::rule_context::CustomRuleContext<'input, 'arena, Tok> + for $ext<'input, 'arena, Tok> + where + Tok: $crate::token::Token + 'input, + { + type NodeKind = $nodekind; + + fn node_tag() -> $nodekind { + $nodekind::$variant + } + + fn get_rule_index(&self) -> usize { + $rule + } + + fn make_node( + arena: &'arena $crate::Arena, + ctx: $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + ) -> *mut $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok> { + arena.alloc_labeled_node($ctxall::Error(ctx)) + } + + fn cast_from<'a>( + node: &'a $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok>, + ) -> ::std::option::Option< + &'a $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + > { + if node.node_tag() + == >::node_tag() + { + ::std::option::Option::Some($crate::cast_unchecked!(node.ctx_ptr() => $crate::parser_rule_context::BaseParserRuleContext<'input, 'arena, Self, Self::NodeKind, Tok>)) + } else { + ::std::option::Option::None + } + } + + fn cast_from_mut<'a>( + node: &'a mut $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok>, + ) -> ::std::option::Option< + &'a mut $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + > { + if node.node_tag() + == >::node_tag() + { + ::std::option::Option::Some($crate::cast_unchecked!(node.ctx_ptr() => mut $crate::parser_rule_context::BaseParserRuleContext<'input, 'arena, Self, Self::NodeKind, Tok>)) + } else { + ::std::option::Option::None + } + } + } + }; + + // `CustomRuleContext` impl for one labeled alternative of a rule: shares + // the base rule's node tag, casts through the `ContextAll` enum. + (@alt $nodekind:ident::$base:ident, $ctxall:ident::$variant:ident, $ext:ident, $rule:expr) => { + impl<'input: 'arena, 'arena, Tok> $crate::rule_context::CustomRuleContext<'input, 'arena, Tok> + for $ext<'input, 'arena, Tok> + where + Tok: $crate::token::Token + 'input, + { + type NodeKind = $nodekind; + + fn node_tag() -> $nodekind { + $nodekind::$base + } + + fn get_rule_index(&self) -> usize { + $rule + } + + fn make_node( + arena: &'arena $crate::Arena, + ctx: $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + ) -> *mut $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok> { + arena.alloc_labeled_node($ctxall::$variant(ctx)) + } + + fn cast_from<'a>( + node: &'a $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok>, + ) -> ::std::option::Option< + &'a $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + > { + if node.node_tag() + == >::node_tag() + { + match $crate::cast_unchecked!(node => $ctxall<'input, 'arena, Tok>) { + $ctxall::$variant(ctx) => ::std::option::Option::Some(ctx), + _ => ::std::option::Option::None, + } + } else { + ::std::option::Option::None + } + } + + fn cast_from_mut<'a>( + node: &'a mut $crate::tree::TreeNode<'input, 'arena, Self::NodeKind, Tok>, + ) -> ::std::option::Option< + &'a mut $crate::parser_rule_context::BaseParserRuleContext< + 'input, + 'arena, + Self, + Self::NodeKind, + Tok, + >, + > { + if node.node_tag() + == >::node_tag() + { + match $crate::cast_unchecked!(node => mut $ctxall<'input, 'arena, Tok>) { + $ctxall::$variant(ctx) => ::std::option::Option::Some(ctx), + _ => ::std::option::Option::None, + } + } else { + ::std::option::Option::None + } + } + } + }; +} + +/// Rule-body scaffolding for generated parser rule functions: enters the +/// rule, runs the body, applies the error strategy on recoverable errors and +/// exits the rule, all inside a stack-growth guard. +/// +/// The recognizer binding is passed in (`recog = self`) so that the body — +/// written at the macro call site — can refer to it. The context constructor +/// is a closure `|parent_ctx| ...` for the same reason. +/// +/// Forms: +/// - `parse_rule!(recog = self, parent_ctx, CtxTy, RULE_x, state, create; { body })` +/// - `parse_rule!(rec recog = self, parent_ctx, parent_state, CtxTy, RULE_x, state, create; prec; { body })` +/// for left-recursive rules (`expr_rec`). +/// - `parse_rule!(catch ...; { body }; [exception arms]; [finally])` (and +/// `catch rec ...`) for rules with `catch`/`finally` blocks. +#[macro_export] +macro_rules! parse_rule { + (catch rec $recog:ident = $self:expr, $parentctx:ident, $parentstate:ident, $ctx:ty, $rule:expr, $state:expr, $create:expr; $prec:ident; $body:block; [$($exceptions:tt)*]; [$($finally:tt)*]) => { + $crate::maybe_grow_stack!({ + let $recog = $self; + let $parentctx = $recog.base.take_ctx(); + let $parentstate = $recog.base.get_state(); + $recog + .base + .enter_recursion_rule(($create)($parentctx)?, $state, $rule, $prec)?; + let result: ::std::result::Result<(), $crate::errors::ANTLRError> = (|| { + $body + ::std::result::Result::Ok(()) + })(); + match result { + ::std::result::Result::Ok(_) => {} + $($exceptions)* + ::std::result::Result::Err(e) => { + if !e.is_recoverable() { + return ::std::result::Result::Err(e); + } + $recog.err_handler.report_error(&mut $recog.base, &e); + $recog.err_handler.recover(&mut $recog.base, &e)?; + } + } + $($finally)* + $recog + .base + .unroll_recursion_context($parentctx) + .map(|ctx| ctx.as_rule_context().unwrap()) + }) + }; + + (catch $recog:ident = $self:expr, $parentctx:ident, $ctx:ty, $rule:expr, $state:expr, $create:expr; $body:block; [$($exceptions:tt)*]; [$($finally:tt)*]) => { + $crate::maybe_grow_stack!({ + let $recog = $self; + let $parentctx = $recog.base.take_ctx(); + $recog.base.enter_rule(($create)($parentctx)?, $state, $rule)?; + let result: ::std::result::Result<(), $crate::errors::ANTLRError> = (|| { + $body + ::std::result::Result::Ok(()) + })(); + match result { + ::std::result::Result::Ok(_) => {} + $($exceptions)* + ::std::result::Result::Err(e) => { + if !e.is_recoverable() { + return ::std::result::Result::Err(e); + } + $recog.err_handler.report_error(&mut $recog.base, &e); + $recog.err_handler.recover(&mut $recog.base, &e)?; + } + } + $($finally)* + $recog + .base + .exit_rule() + .map(|ctx: &'arena _| ctx.as_rule_context().unwrap()) + }) + }; + + (rec $recog:ident = $self:expr, $parentctx:ident, $parentstate:ident, $ctx:ty, $rule:expr, $state:expr, $create:expr; $prec:ident; $body:block) => { + $crate::maybe_grow_stack!({ + let $recog = $self; + let $parentctx = $recog.base.take_ctx(); + let $parentstate = $recog.base.get_state(); + $recog + .base + .enter_recursion_rule(($create)($parentctx)?, $state, $rule, $prec)?; + let result: ::std::result::Result<(), $crate::errors::ANTLRError> = (|| { + $body + ::std::result::Result::Ok(()) + })(); + match result { + ::std::result::Result::Ok(_) => {} + ::std::result::Result::Err(e) => { + if !e.is_recoverable() { + return ::std::result::Result::Err(e); + } + $recog.err_handler.report_error(&mut $recog.base, &e); + $recog.err_handler.recover(&mut $recog.base, &e)?; + } + } + $recog + .base + .unroll_recursion_context($parentctx) + .map(|ctx| ctx.as_rule_context().unwrap()) + }) + }; + + ($recog:ident = $self:expr, $parentctx:ident, $ctx:ty, $rule:expr, $state:expr, $create:expr; $body:block) => { + $crate::maybe_grow_stack!({ + let $recog = $self; + let $parentctx = $recog.base.take_ctx(); + $recog.base.enter_rule(($create)($parentctx)?, $state, $rule)?; + let result: ::std::result::Result<(), $crate::errors::ANTLRError> = (|| { + $body + ::std::result::Result::Ok(()) + })(); + match result { + ::std::result::Result::Ok(_) => {} + ::std::result::Result::Err(e) => { + if !e.is_recoverable() { + return ::std::result::Result::Err(e); + } + $recog.err_handler.report_error(&mut $recog.base, &e); + $recog.err_handler.recover(&mut $recog.base, &e)?; + } + } + $recog + .base + .exit_rule() + .map(|ctx: &'arena _| ctx.as_rule_context().unwrap()) + }) + }; +} + +/// Emits the `ParserRecog` and `Actions` impls for a generated parser's +/// extension struct. References the module-level `ruleNames`, `VOCABULARY` +/// and `ATN_SIMULATOR_MANAGER` items of the generated file. +/// +/// With `; sempred (NodeTy, ParserName) { rule_index => rule_sempred, ... }` +/// an `Actions::sempred` dispatching to the parser's per-rule predicate +/// functions is also generated. +#[macro_export] +macro_rules! impl_parser_recog { + ($ext:ident, $nodekind:ident, $file:literal + $(; sempred ($node:ty, $parser:ident) { $($srule:expr => $sfn:ident,)* })? + ) => { + impl<'input, 'arena, Input, TF> + $crate::parser::ParserRecog< + 'input, + 'arena, + $crate::parser::BaseParser<'input, 'arena, $ext<'input, 'arena>, $nodekind, Input, TF>, + TF::Tok, + > for $ext<'input, 'arena> + where + 'input: 'arena, + TF: $crate::token_factory::TokenFactory<'input, 'arena> + 'arena, + Input: $crate::token_stream::TokenStream<'input, 'arena, TF> + 'arena, + { + fn get_atn_simulator_man( + &self, + ) -> &'static $crate::atn_simulator::ParserATNSimulatorManager { + &ATN_SIMULATOR_MANAGER + } + } + + impl<'input, 'arena, Input, TF> + $crate::recognizer::Actions< + 'input, + 'arena, + $crate::parser::BaseParser<'input, 'arena, $ext<'input, 'arena>, $nodekind, Input, TF>, + TF::Tok, + > for $ext<'input, 'arena> + where + 'input: 'arena, + TF: $crate::token_factory::TokenFactory<'input, 'arena> + 'arena, + Input: $crate::token_stream::TokenStream<'input, 'arena, TF> + 'arena, + { + fn get_grammar_file_name(&self) -> &str { + $file + } + + fn get_rule_names(&self) -> &[&str] { + &ruleNames + } + + fn get_vocabulary(&self) -> &dyn $crate::vocabulary::Vocabulary { + &**VOCABULARY + } + + $( + fn sempred( + _localctx: ::std::option::Option<&'arena $node>, + rule_index: i32, + pred_index: i32, + recog: &mut $crate::parser::BaseParser< + 'input, + 'arena, + $ext<'input, 'arena>, + $nodekind, + Input, + TF, + >, + ) -> bool { + match rule_index { + $( + $srule => $parser::<'input, 'arena, Input, TF>::$sfn( + _localctx.and_then(|x| x.as_rule_context()), + pred_index, + recog, + ), + )* + _ => true, + } + } + )? + } + }; +} + +/// Emits the `Actions` and `LexerRecog` impls for a generated lexer's +/// actions struct. References the module-level `BaseLexerType` alias, +/// `ruleNames`, `_LITERAL_NAMES`, `_SYMBOLIC_NAMES` and +/// `ATN_SIMULATOR_MANAGER` items of the generated file. +/// +/// Optional sections: `; action { rule_index => rule_action, ... }` and +/// `; sempred { rule_index => rule_sempred, ... }` dispatch to the per-rule +/// functions on the actions struct; `; extend { ... }` injects extra members +/// (e.g. a `before_emit` override) into the `LexerRecog` impl. +#[macro_export] +macro_rules! impl_lexer_recog { + ($actions:ident, $file:literal + $(; action { $($arule:expr => $afn:ident,)* })? + $(; sempred { $($srule:expr => $sfn:ident,)* })? + $(; extend { $($extend:item)* })? + ) => { + impl<'input, 'arena, Input, TF> + $crate::recognizer::Actions< + 'input, + 'arena, + BaseLexerType<'input, 'arena, Input, TF>, + TF::Tok, + > for $actions + where + 'input: 'arena, + Input: $crate::char_stream::CharStream<'input>, + TF: $crate::token_factory::TokenFactory<'input, 'arena> + 'arena, + { + $( + fn action( + _localctx: ::std::option::Option< + &'arena $crate::rule_context::EmptyRuleNode<'input, 'arena, TF::Tok>, + >, + rule_index: i32, + action_index: i32, + recog: &mut BaseLexerType<'input, 'arena, Input, TF>, + ) { + match rule_index { + $( + $arule => $actions::$afn(action_index, recog), + )* + _ => {} + } + } + )? + + $( + fn sempred( + _localctx: ::std::option::Option< + &'arena $crate::rule_context::EmptyRuleNode<'input, 'arena, TF::Tok>, + >, + rule_index: i32, + pred_index: i32, + recog: &mut BaseLexerType<'input, 'arena, Input, TF>, + ) -> bool { + match rule_index { + $( + $srule => $actions::$sfn(pred_index, recog), + )* + _ => true, + } + } + )? + } + + impl<'input, 'arena, Input, TF> + $crate::lexer::LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> + for $actions + where + 'input: 'arena, + Input: $crate::char_stream::CharStream<'input>, + TF: $crate::token_factory::TokenFactory<'input, 'arena> + 'arena, + { + $($($extend)*)? + + fn get_rule_names(&self) -> &'static [&'static str] { + &ruleNames + } + + fn get_literal_names(&self) -> &[::std::option::Option<&str>] { + &_LITERAL_NAMES + } + + fn get_symbolic_names(&self) -> &[::std::option::Option<&str>] { + &_SYMBOLIC_NAMES + } + + fn get_grammar_file_name(&self) -> &'static str { + $file + } + + fn get_atn_simulator_man( + &self, + ) -> &'static $crate::atn_simulator::LexerATNSimulatorManager { + &ATN_SIMULATOR_MANAGER + } + } + }; +} diff --git a/runtime/Rust/src/prelude.rs b/runtime/Rust/src/prelude.rs new file mode 100644 index 0000000000..c68d585682 --- /dev/null +++ b/runtime/Rust/src/prelude.rs @@ -0,0 +1,41 @@ +//! Glob-import target for generated code. +//! +//! `use dbt_antlr4::prelude::*;` brings in every name referenced by the +//! boilerplate ANTLR emits (including the expansions of this crate's +//! `impl_*` macros), replacing the long per-file import lists the code +//! generator used to emit. Names a particular grammar does not use are +//! simply ignored, so generated files no longer need +//! `#![allow(unused_imports)]` to compensate for over-importing. + +pub use std::marker::PhantomData; +pub use std::ops::{Deref, DerefMut}; +pub use std::rc::Rc; +pub use std::sync::LazyLock; + +pub use crate::arena::Arena; +pub use crate::atn::{ATN, INVALID_ALT}; +pub use crate::atn_config_set::{ATNConfigSet, LexerATNConfigSet}; +pub use crate::atn_deserializer::ATNDeserializer; +pub use crate::atn_simulator::{ + BaseATNSimulator, LexerATNSimulatorManager, ParserATNSimulatorManager, +}; +pub use crate::char_stream::CharStream; +pub use crate::error_strategy::{DefaultErrorStrategy, ErrorStrategy, ErrorStrategyDelegate}; +pub use crate::errors::ANTLRError; +pub use crate::int_stream::{IntStream, EOF}; +pub use crate::lexer::{BaseLexer, Lexer, LexerRecog}; +pub use crate::lexer_atn_simulator::{ILexerATNSimulator, LexerATNSimulator}; +pub use crate::parser::{BaseParser, ListenerId, Parser, ParserRecog}; +pub use crate::parser_atn_simulator::ParserATNSimulator; +pub use crate::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; +pub use crate::recognizer::{Actions, Recognizer}; +pub use crate::rule_context::{ + BaseRuleContext, CustomRuleContext, EmptyCustomRuleContext, EmptyNodeKind, EmptyRuleNode, + RuleContext, +}; +pub use crate::token::{CommonToken, OwningToken, Token, TOKEN_EOF}; +pub use crate::token_factory::{CommonTokenFactory, TokenFactory}; +pub use crate::token_stream::TokenStream; +pub use crate::tree::*; +pub use crate::vocabulary::{Vocabulary, VocabularyImpl}; +pub use crate::{PredictionContextCache, TokenSource}; diff --git a/runtime/Rust/tests/gen/adaptive/betweenexprlexer.rs b/runtime/Rust/tests/gen/adaptive/betweenexprlexer.rs index cd90e01b94..a63704b494 100644 --- a/runtime/Rust/tests/gen/adaptive/betweenexprlexer.rs +++ b/runtime/Rust/tests/gen/adaptive/betweenexprlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -104,27 +87,7 @@ pub struct BetweenExprLexerActions { impl BetweenExprLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for BetweenExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for BetweenExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "BetweenExprLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { BetweenExprLexerActions, "BetweenExprLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs b/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs index 429f75e678..b671274b82 100644 --- a/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/adaptive/betweenexprparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::betweenexprlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const BetweenExpr_T__0:i32=1; pub const BetweenExpr_T__1:i32=2; @@ -176,33 +151,8 @@ pub struct BetweenExprParserExt<'input, 'arena> { impl<'input, 'arena> BetweenExprParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for BetweenExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for BetweenExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "BetweenExpr.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena BetweenExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 1 => BetweenExprParser::<'input, 'arena, Input, TF>::b_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - 3 => BetweenExprParser::<'input, 'arena, Input, TF>::v_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { BetweenExprParserExt, BetweenExprParserNodeKind, "BetweenExpr.g4"; sempred (BetweenExprParserNode<'input, 'arena, TF::Tok>, BetweenExprParser) { 1 => b_sempred, +3 => v_sempred, } } impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> where @@ -239,53 +189,7 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { BetweenExprParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -319,33 +223,18 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule b*/ - recog.base.set_state(10); - recog.b_rec(0)?; - recog.base.set_state(11); - recog.base.match_token(BetweenExpr_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule b*/ + recog.base.set_state(10); + recog.b_rec(0)?; + recog.base.set_state(11); + recog.base.match_token(BetweenExpr_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- b ---------------- @@ -393,39 +282,7 @@ pub struct BContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for BContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: BContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a BContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => BContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut BContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut BContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled BetweenExprParserNodeKind::BContext, BContextAll, BContextExt, RULE_b } impl<'input: 'arena, 'arena, Tok: Token + 'input> BContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -435,7 +292,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> BContextExt<'input, 'arena, To ) } } - pub trait BContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -471,42 +327,7 @@ pub struct NotContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NotContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: NotContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::NotContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NotContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { - BContextAll::NotContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NotContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { - BContextAll::NotContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::BContext, BContextAll::NotContext, NotContextExt, RULE_b } impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> where @@ -571,42 +392,7 @@ pub struct PredicatedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Co pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PredicatedContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: PredicatedContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::PredicatedContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PredicatedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { - BContextAll::PredicatedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PredicatedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { - BContextAll::PredicatedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::BContext, BContextAll::PredicatedContext, PredicatedContextExt, RULE_b } impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> where @@ -671,42 +457,7 @@ pub struct OrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToke pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for OrContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: OrContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::OrContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a OrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { - BContextAll::OrContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut OrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { - BContextAll::OrContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::BContext, BContextAll::OrContext, OrContextExt, RULE_b } impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> where @@ -771,42 +522,7 @@ pub struct AndContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AndContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: AndContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::AndContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AndContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { - BContextAll::AndContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AndContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { - BContextAll::AndContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::BContext, BContextAll::AndContext, AndContextExt, RULE_b } impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> where @@ -857,127 +573,112 @@ where } fn b_rec(&mut self, _p: i32) -> Result<&'arena BContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(BContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_b, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, BContext, RULE_b, 2, |_parentctx| BContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena BContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 2; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(20); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - BetweenExpr_T__11 |BetweenExpr_ID |BetweenExpr_INT => { - { - recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - /*InvokeRule v*/ - recog.base.set_state(14); - recog.v_rec(0)?; - recog.base.set_state(16); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(0,&mut recog.base)? { - x if x == 1=>{ - { - /*InvokeRule pred*/ - recog.base.set_state(15); - recog.pred()?; - } - } - - _ => {} - } - }} - BetweenExpr_T__0 => { - { - recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(18); - recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(19); - recog.b_rec(3)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(30); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(28); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AndContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(22); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(23); - recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(24); - recog.b_rec(3)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(20); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + BetweenExpr_T__11 |BetweenExpr_ID |BetweenExpr_INT => { + { + recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + /*InvokeRule v*/ + recog.base.set_state(14); + recog.v_rec(0)?; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(0,&mut recog.base)? { + x if x == 1=>{ + { + /*InvokeRule pred*/ + recog.base.set_state(15); + recog.pred()?; + } + } + + _ => {} + } + }} + BetweenExpr_T__0 => { + { + recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(18); + recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(19); + recog.b_rec(3)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(28); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AndContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(22); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - OrContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; - let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(25); - if !({recog.precpred(None, 1)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; - } - recog.base.set_state(26); - recog.base.match_token(BetweenExpr_T__2,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(27); - recog.b_rec(2)?; - } + recog.base.set_state(23); + recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(24); + recog.b_rec(3)?; } - - _ => {} } - } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + OrContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(25); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(26); + recog.base.match_token(BetweenExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(27); + recog.b_rec(2)?; + } + } + + _ => {} } - recog.base.set_state(32); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + } + }) } } //------------------- pred ---------------- @@ -1021,39 +722,7 @@ pub struct PredContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PredContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: PredContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PredContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PredContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PredContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PredContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled BetweenExprParserNodeKind::PredContext, PredContextAll, PredContextExt, RULE_pred } impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -1063,7 +732,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, ) } } - pub trait PredContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -1099,42 +767,7 @@ pub struct CmpContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CmpContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: CmpContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::CmpContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a CmpContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { - PredContextAll::CmpContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut CmpContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { - PredContextAll::CmpContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::PredContext, PredContextAll::CmpContext, CmpContextExt, RULE_pred } impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> where @@ -1199,42 +832,7 @@ pub struct BetweenContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Commo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for BetweenContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: BetweenContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::BetweenContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a BetweenContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { - PredContextAll::BetweenContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut BetweenContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { - PredContextAll::BetweenContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::PredContext, PredContextAll::BetweenContext, BetweenContextExt, RULE_pred } impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for BetweenContext<'input, 'arena, Tok> where @@ -1280,133 +878,72 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn pred(&mut self,) -> Result<&'arena PredContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_pred)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, PredContext, RULE_pred, 4, |_parentctx| PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena PredContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(43); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - BetweenExpr_T__0 |BetweenExpr_T__3 => { - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - BetweenContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena BetweenContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(34); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if _la==BetweenExpr_T__0 { - { - recog.base.set_state(33); - recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; - } - } - - recog.base.set_state(36); - recog.base.match_token(BetweenExpr_T__3,&mut recog.err_handler)?; - /*InvokeRule v*/ - recog.base.set_state(37); - recog.v_rec(0)?; - recog.base.set_state(38); - recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule v*/ - recog.base.set_state(39); - recog.v_rec(0)?; - }} - BetweenExpr_T__4 |BetweenExpr_T__5 |BetweenExpr_T__6 => { - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - CmpContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(41); - _la = recog.base.input.la(1); - if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 224) != 0)) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule v*/ - recog.base.set_state(42); - recog.v_rec(0)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + BetweenExpr_T__0 |BetweenExpr_T__3 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + BetweenContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena BetweenContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(34); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==BetweenExpr_T__0 { + { + recog.base.set_state(33); + recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; + } + } + + recog.base.set_state(36); + recog.base.match_token(BetweenExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule v*/ + recog.base.set_state(37); + recog.v_rec(0)?; + recog.base.set_state(38); + recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule v*/ + recog.base.set_state(39); + recog.v_rec(0)?; + }} + BetweenExpr_T__4 |BetweenExpr_T__5 |BetweenExpr_T__6 => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + CmpContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(41); + _la = recog.base.input.la(1); + if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 224) != 0)) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(42); + recog.v_rec(0)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- v ---------------- pub type VContextAll<'input, 'arena, Tok = CommonToken<'input>> = VContext<'input, 'arena, Tok>; -pub type VContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, VContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct VContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for VContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::VContext } - fn get_rule_index(&self) -> usize { RULE_v } - fn make_node( - arena: &'arena Arena, - ctx: VContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a VContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => VContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut VContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut VContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> VContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, VContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { BetweenExprParserNodeKind, VContext, VContextExt, RULE_v } pub trait VContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1445,160 +982,99 @@ where } fn v_rec(&mut self, _p: i32) -> Result<&'arena VContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(VContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_v, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, VContext, RULE_v, 6, |_parentctx| VContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena VContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 6; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - { - /*InvokeRule atom*/ - recog.base.set_state(46); - recog.atom()?; - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(56); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(7,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(54); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(6,&mut recog.base)? { - 1 =>{ - { - /*recRuleAltStartAction*/ - let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; - - recog.base.set_state(48); - if !({recog.precpred(None, 3)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; - } - recog.base.set_state(49); - _la = recog.base.input.la(1); - if { !(_la==BetweenExpr_T__7 || _la==BetweenExpr_T__8) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule v*/ - recog.base.set_state(50); - recog.v_rec(4)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + { + /*InvokeRule atom*/ + recog.base.set_state(46); + recog.atom()?; + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(56); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(7,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(54); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(6,&mut recog.base)? { + 1 =>{ + { + /*recRuleAltStartAction*/ + let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; + + recog.base.set_state(48); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleAltStartAction*/ - let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; - - recog.base.set_state(51); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(52); - _la = recog.base.input.la(1); - if { !(_la==BetweenExpr_T__9 || _la==BetweenExpr_T__10) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule v*/ - recog.base.set_state(53); - recog.v_rec(3)?; - } + recog.base.set_state(49); + _la = recog.base.input.la(1); + if { !(_la==BetweenExpr_T__7 || _la==BetweenExpr_T__8) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(50); + recog.v_rec(4)?; + } + } + , + 2 =>{ + { + /*recRuleAltStartAction*/ + let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; + + recog.base.set_state(51); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(52); + _la = recog.base.input.la(1); + if { !(_la==BetweenExpr_T__9 || _la==BetweenExpr_T__10) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(53); + recog.v_rec(3)?; } - - _ => {} } - } + + _ => {} } - recog.base.set_state(58); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(7,&mut recog.base)?; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(58); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(7,&mut recog.base)?; } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + } + }) } } //------------------- atom ---------------- pub type AtomContextAll<'input, 'arena, Tok = CommonToken<'input>> = AtomContext<'input, 'arena, Tok>; -pub type AtomContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AtomContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct AtomContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AtomContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::AtomContext } - fn get_rule_index(&self) -> usize { RULE_atom } - fn make_node( - arena: &'arena Arena, - ctx: AtomContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AtomContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AtomContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AtomContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AtomContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> AtomContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, AtomContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { BetweenExprParserNodeKind, AtomContext, AtomContextExt, RULE_atom } pub trait AtomContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1640,75 +1116,60 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn atom(&mut self,) -> Result<&'arena AtomContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_atom)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, AtomContext, RULE_atom, 8, |_parentctx| AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena AtomContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(68); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(8,&mut recog.base)? { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(59); - recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; - } - } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - recog.base.set_state(60); - recog.base.match_token(BetweenExpr_INT,&mut recog.err_handler)?; - } + recog.base.set_state(68); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(8,&mut recog.base)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(59); + recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; } - , - 3 =>{ - /*------- Outer Most Alt 3 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } - { - recog.base.set_state(61); - recog.base.match_token(BetweenExpr_T__11,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(62); - recog.b_rec(0)?; - recog.base.set_state(63); - recog.base.match_token(BetweenExpr_T__12,&mut recog.err_handler)?; - } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(60); + recog.base.match_token(BetweenExpr_INT,&mut recog.err_handler)?; } - , - 4 =>{ - /*------- Outer Most Alt 4 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } - { - recog.base.set_state(65); - recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; - recog.base.set_state(66); - recog.base.match_token(BetweenExpr_T__13,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(67); - recog.b_rec(0)?; - } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(61); + recog.base.match_token(BetweenExpr_T__11,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(62); + recog.b_rec(0)?; + recog.base.set_state(63); + recog.base.match_token(BetweenExpr_T__12,&mut recog.err_handler)?; } - - _ => {} } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + , + 4 =>{ + /*------- Outer Most Alt 4 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } + { + recog.base.set_state(65); + recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; + recog.base.set_state(66); + recog.base.match_token(BetweenExpr_T__13,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(67); + recog.b_rec(0)?; + } } + + _ => {} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/adaptive/fuzzexprlexer.rs b/runtime/Rust/tests/gen/adaptive/fuzzexprlexer.rs index 60aec0da14..296a32224f 100644 --- a/runtime/Rust/tests/gen/adaptive/fuzzexprlexer.rs +++ b/runtime/Rust/tests/gen/adaptive/fuzzexprlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -103,27 +86,7 @@ pub struct FuzzExprLexerActions { impl FuzzExprLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for FuzzExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for FuzzExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "FuzzExprLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { FuzzExprLexerActions, "FuzzExprLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/adaptive/fuzzexprparser.rs b/runtime/Rust/tests/gen/adaptive/fuzzexprparser.rs index 04b78d0a83..b76fe72627 100644 --- a/runtime/Rust/tests/gen/adaptive/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/adaptive/fuzzexprparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::fuzzexprlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const FuzzExpr_T__0:i32=1; pub const FuzzExpr_T__1:i32=2; @@ -177,32 +152,7 @@ pub struct FuzzExprParserExt<'input, 'arena> { impl<'input, 'arena> FuzzExprParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for FuzzExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for FuzzExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "FuzzExpr.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena FuzzExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 4 => FuzzExprParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { FuzzExprParserExt, FuzzExprParserNodeKind, "FuzzExpr.g4"; sempred (FuzzExprParserNode<'input, 'arena, TF::Tok>, FuzzExprParser) { 4 => e_sempred, } } impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> where @@ -232,53 +182,7 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -316,113 +220,52 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule item*/ + recog.base.set_state(12); + recog.item()?; + recog.base.set_state(17); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==FuzzExpr_T__0 { + { { + recog.base.set_state(13); + recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; /*InvokeRule item*/ - recog.base.set_state(12); + recog.base.set_state(14); recog.item()?; - recog.base.set_state(17); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - while _la==FuzzExpr_T__0 { - { - { - recog.base.set_state(13); - recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule item*/ - recog.base.set_state(14); - recog.item()?; - } - } - recog.base.set_state(19); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); } - recog.base.set_state(21); + } + recog.base.set_state(19); recog.err_handler.sync(&mut recog.base)?; _la = recog.base.input.la(1); - if _la==FuzzExpr_T__1 { - { - recog.base.set_state(20); - recog.base.match_token(FuzzExpr_T__1,&mut recog.err_handler)?; - } + } + recog.base.set_state(21); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==FuzzExpr_T__1 { + { + recog.base.set_state(20); + recog.base.match_token(FuzzExpr_T__1,&mut recog.err_handler)?; } + } - recog.base.set_state(23); - recog.base.match_token(FuzzExpr_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(23); + recog.base.match_token(FuzzExpr_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- item ---------------- pub type ItemContextAll<'input, 'arena, Tok = CommonToken<'input>> = ItemContext<'input, 'arena, Tok>; -pub type ItemContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ItemContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct ItemContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ItemContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::ItemContext } - fn get_rule_index(&self) -> usize { RULE_item } - fn make_node( - arena: &'arena Arena, - ctx: ItemContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ItemContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ItemContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ItemContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ItemContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> ItemContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, ItemContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, ItemContext, ItemContextExt, RULE_item } pub trait ItemContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -452,106 +295,45 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn item(&mut self,) -> Result<&'arena ItemContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(ItemContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_item)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, ItemContext, RULE_item, 2, |_parentctx| ItemContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena ItemContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(30); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule e*/ - recog.base.set_state(25); - recog.e_rec(0)?; - recog.base.set_state(26); - recog.base.match_token(FuzzExpr_T__2,&mut recog.err_handler)?; - /*InvokeRule name*/ - recog.base.set_state(27); - recog.name()?; - } - } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - /*InvokeRule e*/ - recog.base.set_state(29); - recog.e_rec(0)?; - } + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(25); + recog.e_rec(0)?; + recog.base.set_state(26); + recog.base.match_token(FuzzExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(27); + recog.name()?; } - - _ => {} } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + /*InvokeRule e*/ + recog.base.set_state(29); + recog.e_rec(0)?; + } } + + _ => {} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- name ---------------- pub type NameContextAll<'input, 'arena, Tok = CommonToken<'input>> = NameContext<'input, 'arena, Tok>; -pub type NameContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NameContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct NameContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for NameContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::NameContext } - fn get_rule_index(&self) -> usize { RULE_name } - fn make_node( - arena: &'arena Arena, - ctx: NameContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NameContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => NameContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NameContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut NameContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> NameContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, NameContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, NameContext, NameContextExt, RULE_name } pub trait NameContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -581,91 +363,30 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn name(&mut self,) -> Result<&'arena NameContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_name)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, NameContext, RULE_name, 4, |_parentctx| NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena NameContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(32); - _la = recog.base.input.la(1); - if { !(_la==FuzzExpr_T__2 || _la==FuzzExpr_ID) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__2 || _la==FuzzExpr_ID) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + } + }) } } //------------------- q ---------------- pub type QContextAll<'input, 'arena, Tok = CommonToken<'input>> = QContext<'input, 'arena, Tok>; -pub type QContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, QContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct QContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for QContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: QContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a QContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => QContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut QContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut QContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, QContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, QContext, QContextExt, RULE_q } pub trait QContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -695,103 +416,42 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn q(&mut self,) -> Result<&'arena QContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(QContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_q)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, QContext, RULE_q, 6, |_parentctx| QContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena QContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule name*/ - recog.base.set_state(34); - recog.name()?; - recog.base.set_state(39); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - { - { - recog.base.set_state(35); - recog.base.match_token(FuzzExpr_T__3,&mut recog.err_handler)?; - /*InvokeRule name*/ - recog.base.set_state(36); - recog.name()?; - } - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule name*/ + recog.base.set_state(34); + recog.name()?; + recog.base.set_state(39); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + { + { + recog.base.set_state(35); + recog.base.match_token(FuzzExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(36); + recog.name()?; } - recog.base.set_state(41); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; - } - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + } } + recog.base.set_state(41); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + } } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- e ---------------- pub type EContextAll<'input, 'arena, Tok = CommonToken<'input>> = EContext<'input, 'arena, Tok>; -pub type EContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: EContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, EContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, EContext, EContextExt, RULE_e } pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -830,212 +490,151 @@ where } fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_e, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, EContext, RULE_e, 8, |_parentctx| EContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 8; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(46); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - FuzzExpr_T__6 => { - { - recog.base.set_state(43); - recog.base.match_token(FuzzExpr_T__6,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(44); - recog.e_rec(5)?; - }} - FuzzExpr_T__2 |FuzzExpr_T__11 |FuzzExpr_ID |FuzzExpr_INT => { - { - /*InvokeRule atom*/ - recog.base.set_state(45); - recog.atom()?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(64); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(6,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(62); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(5,&mut recog.base)? { - 1 =>{ - { - /*recRuleAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(46); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + FuzzExpr_T__6 => { + { + recog.base.set_state(43); + recog.base.match_token(FuzzExpr_T__6,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(44); + recog.e_rec(5)?; + }} + FuzzExpr_T__2 |FuzzExpr_T__11 |FuzzExpr_ID |FuzzExpr_INT => { + { + /*InvokeRule atom*/ + recog.base.set_state(45); + recog.atom()?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(64); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(6,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(62); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(5,&mut recog.base)? { + 1 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - recog.base.set_state(48); - if !({recog.precpred(None, 4)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; - } - recog.base.set_state(49); - recog.base.match_token(FuzzExpr_T__7,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(50); - recog.e_rec(4)?; - } + recog.base.set_state(48); + if !({recog.precpred(None, 4)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - - recog.base.set_state(51); - if !({recog.precpred(None, 3)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; - } - recog.base.set_state(52); - _la = recog.base.input.la(1); - if { !(_la==FuzzExpr_T__8 || _la==FuzzExpr_T__9) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(53); - recog.e_rec(4)?; - } + recog.base.set_state(49); + recog.base.match_token(FuzzExpr_T__7,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(50); + recog.e_rec(4)?; } - , - 3 =>{ - { - /*recRuleAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + } + , + 2 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - recog.base.set_state(54); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(55); - _la = recog.base.input.la(1); - if { !(_la==FuzzExpr_T__6 || _la==FuzzExpr_T__10) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(56); - recog.e_rec(3)?; - } + recog.base.set_state(51); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(52); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__8 || _la==FuzzExpr_T__9) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; } - , - 4 =>{ - { - /*recRuleAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + /*InvokeRule e*/ + recog.base.set_state(53); + recog.e_rec(4)?; + } + } + , + 3 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - recog.base.set_state(57); - if !({recog.precpred(None, 6)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; - } - recog.base.set_state(58); - recog.base.match_token(FuzzExpr_T__4,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(59); - recog.e_rec(0)?; - recog.base.set_state(60); - recog.base.match_token(FuzzExpr_T__5,&mut recog.err_handler)?; - } + recog.base.set_state(54); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(55); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__6 || _la==FuzzExpr_T__10) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; } + /*InvokeRule e*/ + recog.base.set_state(56); + recog.e_rec(3)?; + } + } + , + 4 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - _ => {} + recog.base.set_state(57); + if !({recog.precpred(None, 6)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; + } + recog.base.set_state(58); + recog.base.match_token(FuzzExpr_T__4,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(59); + recog.e_rec(0)?; + recog.base.set_state(60); + recog.base.match_token(FuzzExpr_T__5,&mut recog.err_handler)?; + } } - } + + _ => {} } - recog.base.set_state(66); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(6,&mut recog.base)?; - } + } } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(66); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(6,&mut recog.base)?; + } } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + }) } } //------------------- atom ---------------- pub type AtomContextAll<'input, 'arena, Tok = CommonToken<'input>> = AtomContext<'input, 'arena, Tok>; -pub type AtomContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AtomContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct AtomContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AtomContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::AtomContext } - fn get_rule_index(&self) -> usize { RULE_atom } - fn make_node( - arena: &'arena Arena, - ctx: AtomContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AtomContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AtomContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AtomContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AtomContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> AtomContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, AtomContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, AtomContext, AtomContextExt, RULE_atom } pub trait AtomContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1085,104 +684,89 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn atom(&mut self,) -> Result<&'arena AtomContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 10, RULE_atom)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, AtomContext, RULE_atom, 10, |_parentctx| AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena AtomContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(86); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(9,&mut recog.base)? { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule q*/ - recog.base.set_state(67); - recog.q()?; - } + recog.base.set_state(86); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(9,&mut recog.base)? { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule q*/ + recog.base.set_state(67); + recog.q()?; } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - recog.base.set_state(68); - recog.base.match_token(FuzzExpr_INT,&mut recog.err_handler)?; - } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(68); + recog.base.match_token(FuzzExpr_INT,&mut recog.err_handler)?; } - , - 3 =>{ - /*------- Outer Most Alt 3 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(69); + recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(70); + recog.e_rec(0)?; + recog.base.set_state(71); + recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; + } + } + , + 4 =>{ + /*------- Outer Most Alt 4 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } + { + recog.base.set_state(73); + recog.base.match_token(FuzzExpr_ID,&mut recog.err_handler)?; + recog.base.set_state(74); + recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; + recog.base.set_state(83); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if (((_la) & !0x3f) == 0 && ((1usize << _la) & 53384) != 0) { { - recog.base.set_state(69); - recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; /*InvokeRule e*/ - recog.base.set_state(70); + recog.base.set_state(75); recog.e_rec(0)?; - recog.base.set_state(71); - recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; - } - } - , - 4 =>{ - /*------- Outer Most Alt 4 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } - { - recog.base.set_state(73); - recog.base.match_token(FuzzExpr_ID,&mut recog.err_handler)?; - recog.base.set_state(74); - recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; - recog.base.set_state(83); + recog.base.set_state(80); recog.err_handler.sync(&mut recog.base)?; _la = recog.base.input.la(1); - if (((_la) & !0x3f) == 0 && ((1usize << _la) & 53384) != 0) { + while _la==FuzzExpr_T__0 { + { { + recog.base.set_state(76); + recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; /*InvokeRule e*/ - recog.base.set_state(75); + recog.base.set_state(77); recog.e_rec(0)?; - recog.base.set_state(80); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - while _la==FuzzExpr_T__0 { - { - { - recog.base.set_state(76); - recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(77); - recog.e_rec(0)?; - } - } - recog.base.set_state(82); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); } } + recog.base.set_state(82); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); } - - recog.base.set_state(85); - recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; } } - _ => {} - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + recog.base.set_state(85); + recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; + } } + + _ => {} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/adaptive/guardexprlexer.rs b/runtime/Rust/tests/gen/adaptive/guardexprlexer.rs index 31533c85cb..c605be0686 100644 --- a/runtime/Rust/tests/gen/adaptive/guardexprlexer.rs +++ b/runtime/Rust/tests/gen/adaptive/guardexprlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -100,27 +83,7 @@ pub struct GuardExprLexerActions { impl GuardExprLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for GuardExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for GuardExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "GuardExprLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { GuardExprLexerActions, "GuardExprLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/adaptive/guardexprparser.rs b/runtime/Rust/tests/gen/adaptive/guardexprparser.rs index cb932acf68..d135892504 100644 --- a/runtime/Rust/tests/gen/adaptive/guardexprparser.rs +++ b/runtime/Rust/tests/gen/adaptive/guardexprparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::guardexprlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const GuardExpr_T__0:i32=1; pub const GuardExpr_T__1:i32=2; @@ -172,32 +147,7 @@ pub struct GuardExprParserExt<'input, 'arena> { impl<'input, 'arena> GuardExprParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for GuardExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for GuardExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "GuardExpr.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena GuardExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 2 => GuardExprParser::<'input, 'arena, Input, TF>::expr_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { GuardExprParserExt, GuardExprParserNodeKind, "GuardExpr.g4"; sempred (GuardExprParserNode<'input, 'arena, TF::Tok>, GuardExprParser) { 2 => expr_sempred, } } impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> where @@ -221,53 +171,7 @@ where //------------------- prog ---------------- pub type ProgContextAll<'input, 'arena, Tok = CommonToken<'input>> = ProgContext<'input, 'arena, Tok>; -pub type ProgContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ProgContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct ProgContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ProgContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ProgContext } - fn get_rule_index(&self) -> usize { RULE_prog } - fn make_node( - arena: &'arena Arena, - ctx: ProgContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ProgContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ProgContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ProgContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ProgContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> ProgContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, ProgContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { GuardExprParserNodeKind, ProgContext, ProgContextExt, RULE_prog } pub trait ProgContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -305,47 +209,32 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn prog(&mut self,) -> Result<&'arena ProgContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(ProgContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_prog)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, ProgContext, RULE_prog, 0, |_parentctx| ProgContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena ProgContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(11); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { { - recog.base.set_state(11); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - loop { - { - { - /*InvokeRule stmt*/ - recog.base.set_state(10); - recog.stmt()?; - } - } - recog.base.set_state(13); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if !((((_la) & !0x3f) == 0 && ((1usize << _la) & 13330) != 0)) {break} - } - recog.base.set_state(15); - recog.base.match_token(GuardExpr_EOF,&mut recog.err_handler)?; + { + /*InvokeRule stmt*/ + recog.base.set_state(10); + recog.stmt()?; } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; } + recog.base.set_state(13); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !((((_la) & !0x3f) == 0 && ((1usize << _la) & 13330) != 0)) {break} + } + recog.base.set_state(15); + recog.base.match_token(GuardExpr_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- stmt ---------------- @@ -389,39 +278,7 @@ pub struct StmtContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for StmtContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } - fn get_rule_index(&self) -> usize { RULE_stmt } - fn make_node( - arena: &'arena Arena, - ctx: StmtContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StmtContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a StmtContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => StmtContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut StmtContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut StmtContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled GuardExprParserNodeKind::StmtContext, StmtContextAll, StmtContextExt, RULE_stmt } impl<'input: 'arena, 'arena, Tok: Token + 'input> StmtContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -431,7 +288,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> StmtContextExt<'input, 'arena, ) } } - pub trait StmtContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -467,42 +323,7 @@ pub struct EvalContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for EvalContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } - fn get_rule_index(&self) -> usize { RULE_stmt } - fn make_node( - arena: &'arena Arena, - ctx: EvalContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StmtContextAll::EvalContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a EvalContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => StmtContextAll<'input, 'arena, Tok>) { - StmtContextAll::EvalContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut EvalContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut StmtContextAll<'input, 'arena, Tok>) { - StmtContextAll::EvalContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::StmtContext, StmtContextAll::EvalContext, EvalContextExt, RULE_stmt } impl<'input, 'arena, Tok> StmtContextAttrs<'input, 'arena, Tok> for EvalContext<'input, 'arena, Tok> where @@ -567,42 +388,7 @@ pub struct AssignContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AssignContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } - fn get_rule_index(&self) -> usize { RULE_stmt } - fn make_node( - arena: &'arena Arena, - ctx: AssignContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StmtContextAll::AssignContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AssignContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => StmtContextAll<'input, 'arena, Tok>) { - StmtContextAll::AssignContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AssignContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut StmtContextAll<'input, 'arena, Tok>) { - StmtContextAll::AssignContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::StmtContext, StmtContextAll::AssignContext, AssignContextExt, RULE_stmt } impl<'input, 'arena, Tok> StmtContextAttrs<'input, 'arena, Tok> for AssignContext<'input, 'arena, Tok> where @@ -648,64 +434,49 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn stmt(&mut self,) -> Result<&'arena StmtContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(StmtContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_stmt)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, StmtContext, RULE_stmt, 2, |_parentctx| StmtContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena StmtContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(26); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - GuardExpr_T__0 => { - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - AssignContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena AssignContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(17); - recog.base.match_token(GuardExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(18); - recog.expr_rec(0)?; - recog.base.set_state(19); - recog.base.match_token(GuardExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(20); - recog.expr_rec(0)?; - recog.base.set_state(21); - recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; - }} - GuardExpr_T__3 |GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - EvalContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena EvalContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - /*InvokeRule expr*/ - recog.base.set_state(23); - recog.expr_rec(0)?; - recog.base.set_state(24); - recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(26); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__0 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + AssignContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena AssignContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(17); + recog.base.match_token(GuardExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(18); + recog.expr_rec(0)?; + recog.base.set_state(19); + recog.base.match_token(GuardExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(20); + recog.expr_rec(0)?; + recog.base.set_state(21); + recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; + }} + GuardExpr_T__3 |GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + EvalContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena EvalContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + /*InvokeRule expr*/ + recog.base.set_state(23); + recog.expr_rec(0)?; + recog.base.set_state(24); + recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- expr ---------------- @@ -753,39 +524,7 @@ pub struct ExprContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ExprContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: ExprContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ExprContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ExprContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ExprContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ExprContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled GuardExprParserNodeKind::ExprContext, ExprContextAll, ExprContextExt, RULE_expr } impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -795,7 +534,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, ) } } - pub trait ExprContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -831,42 +569,7 @@ pub struct NotContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NotContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: NotContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::NotContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NotContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::NotContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NotContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::NotContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::ExprContext, ExprContextAll::NotContext, NotContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> where @@ -931,42 +634,7 @@ pub struct PredicatedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Co pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PredicatedContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: PredicatedContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::PredicatedContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PredicatedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::PredicatedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PredicatedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::PredicatedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::ExprContext, ExprContextAll::PredicatedContext, PredicatedContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> where @@ -1031,42 +699,7 @@ pub struct OrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToke pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for OrContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: OrContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::OrContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a OrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::OrContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut OrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::OrContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::ExprContext, ExprContextAll::OrContext, OrContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> where @@ -1131,42 +764,7 @@ pub struct AndContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AndContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: AndContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::AndContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AndContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::AndContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AndContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::AndContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::ExprContext, ExprContextAll::AndContext, AndContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> where @@ -1217,127 +815,112 @@ where } fn expr_rec(&mut self, _p: i32) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_expr, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, ExprContext, RULE_expr, 4, |_parentctx| ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena ExprContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 4; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(35); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { - { - recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - /*InvokeRule value*/ - recog.base.set_state(29); - recog.value()?; - recog.base.set_state(31); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { - x if x == 1=>{ - { - /*InvokeRule pred*/ - recog.base.set_state(30); - recog.pred()?; - } - } - - _ => {} - } - }} - GuardExpr_T__3 => { - { - recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(33); - recog.base.match_token(GuardExpr_T__3,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(34); - recog.expr_rec(3)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(45); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(5,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(43); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(4,&mut recog.base)? { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AndContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(37); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(38); - recog.base.match_token(GuardExpr_T__4,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(39); - recog.expr_rec(3)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(35); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { + { + recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + /*InvokeRule value*/ + recog.base.set_state(29); + recog.value()?; + recog.base.set_state(31); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + x if x == 1=>{ + { + /*InvokeRule pred*/ + recog.base.set_state(30); + recog.pred()?; + } + } + + _ => {} + } + }} + GuardExpr_T__3 => { + { + recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(33); + recog.base.match_token(GuardExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(34); + recog.expr_rec(3)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(45); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(5,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(4,&mut recog.base)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AndContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(37); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - OrContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; - let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(40); - if !({recog.precpred(None, 1)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; - } - recog.base.set_state(41); - recog.base.match_token(GuardExpr_T__5,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(42); - recog.expr_rec(2)?; - } + recog.base.set_state(38); + recog.base.match_token(GuardExpr_T__4,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(39); + recog.expr_rec(3)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + OrContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(40); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(41); + recog.base.match_token(GuardExpr_T__5,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(42); + recog.expr_rec(2)?; } - - _ => {} } - } + + _ => {} } - recog.base.set_state(47); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(5,&mut recog.base)?; - } + } } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(47); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(5,&mut recog.base)?; + } } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + }) } } //------------------- pred ---------------- @@ -1381,39 +964,7 @@ pub struct PredContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PredContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: PredContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PredContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PredContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PredContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PredContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled GuardExprParserNodeKind::PredContext, PredContextAll, PredContextExt, RULE_pred } impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -1423,7 +974,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, ) } } - pub trait PredContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -1459,42 +1009,7 @@ pub struct CmpContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CmpContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: CmpContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::CmpContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a CmpContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { - PredContextAll::CmpContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut CmpContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { - PredContextAll::CmpContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::PredContext, PredContextAll::CmpContext, CmpContextExt, RULE_pred } impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> where @@ -1555,42 +1070,7 @@ pub struct InListContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for InListContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: InListContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::InListContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a InListContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { - PredContextAll::InListContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut InListContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { - PredContextAll::InListContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::PredContext, PredContextAll::InListContext, InListContextExt, RULE_pred } impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for InListContext<'input, 'arena, Tok> where @@ -1636,122 +1116,61 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn pred(&mut self,) -> Result<&'arena PredContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_pred)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, PredContext, RULE_pred, 6, |_parentctx| PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena PredContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(55); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - GuardExpr_T__1 |GuardExpr_T__6 |GuardExpr_T__7 => { - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - CmpContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(48); - _la = recog.base.input.la(1); - if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 388) != 0)) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule value*/ - recog.base.set_state(49); - recog.value()?; - }} - GuardExpr_T__8 => { - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - InListContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena InListContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(50); - recog.base.match_token(GuardExpr_T__8,&mut recog.err_handler)?; - recog.base.set_state(51); - recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(52); - recog.expr_rec(0)?; - recog.base.set_state(53); - recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(55); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__1 |GuardExpr_T__6 |GuardExpr_T__7 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + CmpContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(48); + _la = recog.base.input.la(1); + if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 388) != 0)) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule value*/ + recog.base.set_state(49); + recog.value()?; + }} + GuardExpr_T__8 => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + InListContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena InListContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(50); + recog.base.match_token(GuardExpr_T__8,&mut recog.err_handler)?; + recog.base.set_state(51); + recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(52); + recog.expr_rec(0)?; + recog.base.set_state(53); + recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- value ---------------- pub type ValueContextAll<'input, 'arena, Tok = CommonToken<'input>> = ValueContext<'input, 'arena, Tok>; -pub type ValueContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ValueContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct ValueContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ValueContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ValueContext } - fn get_rule_index(&self) -> usize { RULE_value } - fn make_node( - arena: &'arena Arena, - ctx: ValueContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ValueContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ValueContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ValueContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ValueContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> ValueContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, ValueContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { GuardExprParserNodeKind, ValueContext, ValueContextExt, RULE_value } pub trait ValueContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1793,55 +1212,40 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn value(&mut self,) -> Result<&'arena ValueContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(ValueContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_value)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, ValueContext, RULE_value, 8, |_parentctx| ValueContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena ValueContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(63); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - GuardExpr_ID => { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(57); - recog.base.match_token(GuardExpr_ID,&mut recog.err_handler)?; - }} - GuardExpr_INT => { - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - recog.base.set_state(58); - recog.base.match_token(GuardExpr_INT,&mut recog.err_handler)?; - }} - GuardExpr_T__9 => { - /*------- Outer Most Alt 3 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } - { - recog.base.set_state(59); - recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(60); - recog.expr_rec(0)?; - recog.base.set_state(61); - recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(63); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_ID => { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(57); + recog.base.match_token(GuardExpr_ID,&mut recog.err_handler)?; + }} + GuardExpr_INT => { + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(58); + recog.base.match_token(GuardExpr_INT,&mut recog.err_handler)?; + }} + GuardExpr_T__9 => { + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(59); + recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(60); + recog.expr_rec(0)?; + recog.base.set_state(61); + recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/adaptive/parenexprlexer.rs b/runtime/Rust/tests/gen/adaptive/parenexprlexer.rs index 1bc467cf59..12812e1871 100644 --- a/runtime/Rust/tests/gen/adaptive/parenexprlexer.rs +++ b/runtime/Rust/tests/gen/adaptive/parenexprlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -97,27 +80,7 @@ pub struct ParenExprLexerActions { impl ParenExprLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for ParenExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for ParenExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "ParenExprLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { ParenExprLexerActions, "ParenExprLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/adaptive/parenexprparser.rs b/runtime/Rust/tests/gen/adaptive/parenexprparser.rs index c7dc08f0cf..db231f0778 100644 --- a/runtime/Rust/tests/gen/adaptive/parenexprparser.rs +++ b/runtime/Rust/tests/gen/adaptive/parenexprparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::parenexprlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const ParenExpr_T__0:i32=1; pub const ParenExpr_T__1:i32=2; @@ -165,32 +140,7 @@ pub struct ParenExprParserExt<'input, 'arena> { impl<'input, 'arena> ParenExprParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ParenExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ParenExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "ParenExpr.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena ParenExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 1 => ParenExprParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { ParenExprParserExt, ParenExprParserNodeKind, "ParenExpr.g4"; sempred (ParenExprParserNode<'input, 'arena, TF::Tok>, ParenExprParser) { 1 => e_sempred, } } impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> where @@ -214,53 +164,7 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { ParenExprParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -294,33 +198,18 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule e*/ - recog.base.set_state(6); - recog.e_rec(0)?; - recog.base.set_state(7); - recog.base.match_token(ParenExpr_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(6); + recog.e_rec(0)?; + recog.base.set_state(7); + recog.base.match_token(ParenExpr_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- e ---------------- @@ -376,39 +265,7 @@ pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: EContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled ParenExprParserNodeKind::EContext, EContextAll, EContextExt, RULE_e } impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -418,7 +275,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, To ) } } - pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -458,42 +314,7 @@ pub struct AddContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AddContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: AddContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::AddContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::AddContext, AddContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> where @@ -558,42 +379,7 @@ pub struct ColContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ColContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: ColContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::ColContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ColContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::ColContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ColContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::ColContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::ColContext, ColContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ColContext<'input, 'arena, Tok> where @@ -654,42 +440,7 @@ pub struct ParensContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ParensContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: ParensContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::ParensContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ParensContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::ParensContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ParensContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::ParensContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::ParensContext, ParensContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ParensContext<'input, 'arena, Tok> where @@ -750,42 +501,7 @@ pub struct SubqueryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Comm pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for SubqueryContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: SubqueryContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::SubqueryContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SubqueryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::SubqueryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SubqueryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::SubqueryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::SubqueryContext, SubqueryContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for SubqueryContext<'input, 'arena, Tok> where @@ -850,42 +566,7 @@ pub struct RowConstructorContextExt<'input: 'arena, 'arena, Tok: Token + 'input pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for RowConstructorContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: RowConstructorContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::RowConstructorContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a RowConstructorContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::RowConstructorContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut RowConstructorContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::RowConstructorContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::RowConstructorContext, RowConstructorContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for RowConstructorContext<'input, 'arena, Tok> where @@ -950,42 +631,7 @@ pub struct MulContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for MulContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: MulContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::MulContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a MulContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::MulContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut MulContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::MulContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::MulContext, MulContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> where @@ -1050,42 +696,7 @@ pub struct NumContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NumContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: NumContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::NumContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NumContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::NumContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NumContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::NumContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::NumContext, NumContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for NumContext<'input, 'arena, Tok> where @@ -1146,42 +757,7 @@ pub struct UnaryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonT pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for UnaryContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: UnaryContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::UnaryContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a UnaryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::UnaryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut UnaryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::UnaryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::UnaryContext, UnaryContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for UnaryContext<'input, 'arena, Tok> where @@ -1232,203 +808,188 @@ where } fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, EContext, RULE_e, 2, |_parentctx| EContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 2; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(32); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(1,&mut recog.base)? { - 1 =>{ - { - recog.base.with_mut_ctx(|ctx| { NumContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena NumContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(10); - recog.base.match_token(ParenExpr_INT,&mut recog.err_handler)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(1,&mut recog.base)? { + 1 =>{ + { + recog.base.with_mut_ctx(|ctx| { NumContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NumContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(10); + recog.base.match_token(ParenExpr_INT,&mut recog.err_handler)?; } - , - 2 =>{ - { - recog.base.with_mut_ctx(|ctx| { ColContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena ColContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(11); - recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; - } + } + , + 2 =>{ + { + recog.base.with_mut_ctx(|ctx| { ColContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ColContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(11); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; } - , - 3 =>{ + } + , + 3 =>{ + { + recog.base.with_mut_ctx(|ctx| { RowConstructorContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena RowConstructorContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(12); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(13); + recog.e_rec(0)?; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { + { { - recog.base.with_mut_ctx(|ctx| { RowConstructorContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena RowConstructorContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(12); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + recog.base.set_state(14); + recog.base.match_token(ParenExpr_T__1,&mut recog.err_handler)?; /*InvokeRule e*/ - recog.base.set_state(13); + recog.base.set_state(15); recog.e_rec(0)?; - recog.base.set_state(16); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - loop { - { - { - recog.base.set_state(14); - recog.base.match_token(ParenExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(15); - recog.e_rec(0)?; - } - } - recog.base.set_state(18); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if !(_la==ParenExpr_T__1) {break} } - recog.base.set_state(20); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; } + recog.base.set_state(18); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !(_la==ParenExpr_T__1) {break} } - , - 4 =>{ - { - recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(22); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(23); - recog.e_rec(0)?; - recog.base.set_state(24); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - } + recog.base.set_state(20); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; } - , - 5 =>{ - { - recog.base.with_mut_ctx(|ctx| { SubqueryContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena SubqueryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(26); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule q*/ - recog.base.set_state(27); - recog.q()?; - recog.base.set_state(28); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - } + } + , + 4 =>{ + { + recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(22); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(23); + recog.e_rec(0)?; + recog.base.set_state(24); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; } - , - 6 =>{ - { - recog.base.with_mut_ctx(|ctx| { UnaryContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena UnaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(30); - recog.base.match_token(ParenExpr_T__3,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(31); - recog.e_rec(3)?; - } + } + , + 5 =>{ + { + recog.base.with_mut_ctx(|ctx| { SubqueryContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena SubqueryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(26); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule q*/ + recog.base.set_state(27); + recog.q()?; + recog.base.set_state(28); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; } - - _ => {} } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(42); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(40); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - MulContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(34); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(35); - _la = recog.base.input.la(1); - if { !(_la==ParenExpr_T__4 || _la==ParenExpr_T__5) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(36); - recog.e_rec(3)?; - } + , + 6 =>{ + { + recog.base.with_mut_ctx(|ctx| { UnaryContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena UnaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(30); + recog.base.match_token(ParenExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(31); + recog.e_rec(3)?; + } + } + + _ => {} + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(42); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(40); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + MulContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(34); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AddContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(37); - if !({recog.precpred(None, 1)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; - } - recog.base.set_state(38); - _la = recog.base.input.la(1); - if { !(_la==ParenExpr_T__3 || _la==ParenExpr_T__6) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(39); - recog.e_rec(2)?; - } + recog.base.set_state(35); + _la = recog.base.input.la(1); + if { !(_la==ParenExpr_T__4 || _la==ParenExpr_T__5) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(36); + recog.e_rec(3)?; } - - _ => {} } - } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AddContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(37); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(38); + _la = recog.base.input.la(1); + if { !(_la==ParenExpr_T__3 || _la==ParenExpr_T__6) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(39); + recog.e_rec(2)?; + } + } + + _ => {} } - recog.base.set_state(44); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(44); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + } + }) } } //------------------- q ---------------- @@ -1474,39 +1035,7 @@ pub struct QContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for QContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: QContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(QContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a QContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => QContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut QContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut QContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled ParenExprParserNodeKind::QContext, QContextAll, QContextExt, RULE_q } impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -1516,7 +1045,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, To ) } } - pub trait QContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -1556,42 +1084,7 @@ pub struct SelectContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for SelectContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: SelectContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(QContextAll::SelectContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SelectContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { - QContextAll::SelectContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SelectContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { - QContextAll::SelectContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::QContext, QContextAll::SelectContext, SelectContextExt, RULE_q } impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for SelectContext<'input, 'arena, Tok> where @@ -1652,42 +1145,7 @@ pub struct NestedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NestedContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: NestedContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(QContextAll::NestedContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NestedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { - QContextAll::NestedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NestedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { - QContextAll::NestedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::QContext, QContextAll::NestedContext, NestedContextExt, RULE_q } impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for NestedContext<'input, 'arena, Tok> where @@ -1752,42 +1210,7 @@ pub struct TableContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonT pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for TableContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: TableContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(QContextAll::TableContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a TableContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { - QContextAll::TableContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut TableContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { - QContextAll::TableContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::QContext, QContextAll::TableContext, TableContextExt, RULE_q } impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for TableContext<'input, 'arena, Tok> where @@ -1833,69 +1256,54 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn q(&mut self,) -> Result<&'arena QContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(QContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_q)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, QContext, RULE_q, 4, |_parentctx| QContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena QContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(52); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - ParenExpr_T__7 => { - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - SelectContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena SelectContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(45); - recog.base.match_token(ParenExpr_T__7,&mut recog.err_handler)?; - recog.base.set_state(46); - recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; - }} - ParenExpr_ID => { - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - TableContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena TableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(47); - recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; - }} - ParenExpr_T__0 => { - /*------- Outer Most Alt 3 -------*/ - recog.base.with_mut_ctx(|ctx| { - NestedContextExt::copy_from(ctx); - ctx.set_alt_number(3); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena NestedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(48); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule q*/ - recog.base.set_state(49); - recog.q()?; - recog.base.set_state(50); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(52); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + ParenExpr_T__7 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + SelectContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena SelectContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(45); + recog.base.match_token(ParenExpr_T__7,&mut recog.err_handler)?; + recog.base.set_state(46); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + }} + ParenExpr_ID => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + TableContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena TableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(47); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + }} + ParenExpr_T__0 => { + /*------- Outer Most Alt 3 -------*/ + recog.base.with_mut_ctx(|ctx| { + NestedContextExt::copy_from(ctx); + ctx.set_alt_number(3); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena NestedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(48); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule q*/ + recog.base.set_state(49); + recog.q()?; + recog.base.set_state(50); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/betweenexprlexer.rs b/runtime/Rust/tests/gen/betweenexprlexer.rs index cd90e01b94..a63704b494 100644 --- a/runtime/Rust/tests/gen/betweenexprlexer.rs +++ b/runtime/Rust/tests/gen/betweenexprlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -104,27 +87,7 @@ pub struct BetweenExprLexerActions { impl BetweenExprLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for BetweenExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for BetweenExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "BetweenExprLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { BetweenExprLexerActions, "BetweenExprLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index 20d2789998..7fcae31ba5 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::betweenexprlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const BetweenExpr_T__0:i32=1; pub const BetweenExpr_T__1:i32=2; @@ -176,33 +151,8 @@ pub struct BetweenExprParserExt<'input, 'arena> { impl<'input, 'arena> BetweenExprParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for BetweenExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for BetweenExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "BetweenExpr.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena BetweenExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 1 => BetweenExprParser::<'input, 'arena, Input, TF>::b_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - 3 => BetweenExprParser::<'input, 'arena, Input, TF>::v_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { BetweenExprParserExt, BetweenExprParserNodeKind, "BetweenExpr.g4"; sempred (BetweenExprParserNode<'input, 'arena, TF::Tok>, BetweenExprParser) { 1 => b_sempred, +3 => v_sempred, } } impl<'input, 'arena, Input, TF> BetweenExprParser<'input, 'arena, Input, TF> where @@ -239,53 +189,7 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { BetweenExprParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -319,33 +223,18 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule b*/ - recog.base.set_state(10); - recog.b_rec(0)?; - recog.base.set_state(11); - recog.base.match_token(BetweenExpr_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule b*/ + recog.base.set_state(10); + recog.b_rec(0)?; + recog.base.set_state(11); + recog.base.match_token(BetweenExpr_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- b ---------------- @@ -393,39 +282,7 @@ pub struct BContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for BContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: BContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a BContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => BContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut BContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut BContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled BetweenExprParserNodeKind::BContext, BContextAll, BContextExt, RULE_b } impl<'input: 'arena, 'arena, Tok: Token + 'input> BContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -435,7 +292,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> BContextExt<'input, 'arena, To ) } } - pub trait BContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -471,42 +327,7 @@ pub struct NotContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NotContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: NotContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::NotContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NotContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { - BContextAll::NotContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NotContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { - BContextAll::NotContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::BContext, BContextAll::NotContext, NotContextExt, RULE_b } impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> where @@ -571,42 +392,7 @@ pub struct PredicatedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Co pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PredicatedContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: PredicatedContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::PredicatedContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PredicatedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { - BContextAll::PredicatedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PredicatedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { - BContextAll::PredicatedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::BContext, BContextAll::PredicatedContext, PredicatedContextExt, RULE_b } impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> where @@ -671,42 +457,7 @@ pub struct OrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToke pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for OrContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: OrContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::OrContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a OrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { - BContextAll::OrContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut OrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { - BContextAll::OrContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::BContext, BContextAll::OrContext, OrContextExt, RULE_b } impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> where @@ -771,42 +522,7 @@ pub struct AndContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AndContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::BContext } - fn get_rule_index(&self) -> usize { RULE_b } - fn make_node( - arena: &'arena Arena, - ctx: AndContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(BContextAll::AndContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AndContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => BContextAll<'input, 'arena, Tok>) { - BContextAll::AndContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AndContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut BContextAll<'input, 'arena, Tok>) { - BContextAll::AndContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::BContext, BContextAll::AndContext, AndContextExt, RULE_b } impl<'input, 'arena, Tok> BContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> where @@ -857,127 +573,112 @@ where } fn b_rec(&mut self, _p: i32) -> Result<&'arena BContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(BContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_b, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, BContext, RULE_b, 2, |_parentctx| BContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena BContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 2; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(20); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - BetweenExpr_T__11 |BetweenExpr_ID |BetweenExpr_INT => { - { - recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - /*InvokeRule v*/ - recog.base.set_state(14); - recog.v_rec(0)?; - recog.base.set_state(16); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(0)?; _sdp } { - x if x == 1 =>{ - { - /*InvokeRule pred*/ - recog.base.set_state(15); - recog.pred()?; - } - } - - _ => {} - } - }} - BetweenExpr_T__0 => { - { - recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(18); - recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(19); - recog.b_rec(3)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(30); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(28); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(2)?; _sdp } { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AndContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(22); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(23); - recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(24); - recog.b_rec(3)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(20); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + BetweenExpr_T__11 |BetweenExpr_ID |BetweenExpr_INT => { + { + recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + /*InvokeRule v*/ + recog.base.set_state(14); + recog.v_rec(0)?; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(0)?; _sdp } { + x if x == 1 =>{ + { + /*InvokeRule pred*/ + recog.base.set_state(15); + recog.pred()?; + } + } + + _ => {} + } + }} + BetweenExpr_T__0 => { + { + recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(18); + recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(19); + recog.b_rec(3)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(28); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(2)?; _sdp } { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AndContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(22); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - OrContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; - let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(25); - if !({recog.precpred(None, 1)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; - } - recog.base.set_state(26); - recog.base.match_token(BetweenExpr_T__2,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(27); - recog.b_rec(2)?; - } + recog.base.set_state(23); + recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(24); + recog.b_rec(3)?; } - - _ => {} } - } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = BContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + OrContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_b)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(25); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(26); + recog.base.match_token(BetweenExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(27); + recog.b_rec(2)?; + } + } + + _ => {} } - recog.base.set_state(32); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + } + }) } } //------------------- pred ---------------- @@ -1021,39 +722,7 @@ pub struct PredContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PredContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: PredContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PredContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PredContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PredContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PredContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled BetweenExprParserNodeKind::PredContext, PredContextAll, PredContextExt, RULE_pred } impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -1063,7 +732,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, ) } } - pub trait PredContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -1099,42 +767,7 @@ pub struct CmpContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CmpContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: CmpContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::CmpContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a CmpContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { - PredContextAll::CmpContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut CmpContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { - PredContextAll::CmpContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::PredContext, PredContextAll::CmpContext, CmpContextExt, RULE_pred } impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> where @@ -1199,42 +832,7 @@ pub struct BetweenContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Commo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for BetweenContextExt<'input, 'arena, Tok> -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: BetweenContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::BetweenContext(ctx)) - } - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a BetweenContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { - PredContextAll::BetweenContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut BetweenContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { - PredContextAll::BetweenContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt BetweenExprParserNodeKind::PredContext, PredContextAll::BetweenContext, BetweenContextExt, RULE_pred } impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for BetweenContext<'input, 'arena, Tok> where @@ -1280,133 +878,72 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn pred(&mut self,) -> Result<&'arena PredContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_pred)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, PredContext, RULE_pred, 4, |_parentctx| PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena PredContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(43); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - BetweenExpr_T__0 |BetweenExpr_T__3 => { - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - BetweenContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena BetweenContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(34); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if _la==BetweenExpr_T__0 { - { - recog.base.set_state(33); - recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; - } - } - - recog.base.set_state(36); - recog.base.match_token(BetweenExpr_T__3,&mut recog.err_handler)?; - /*InvokeRule v*/ - recog.base.set_state(37); - recog.v_rec(0)?; - recog.base.set_state(38); - recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule v*/ - recog.base.set_state(39); - recog.v_rec(0)?; - }} - BetweenExpr_T__4 |BetweenExpr_T__5 |BetweenExpr_T__6 => { - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - CmpContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(41); - _la = recog.base.input.la(1); - if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 224) != 0)) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule v*/ - recog.base.set_state(42); - recog.v_rec(0)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + BetweenExpr_T__0 |BetweenExpr_T__3 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + BetweenContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena BetweenContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(34); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==BetweenExpr_T__0 { + { + recog.base.set_state(33); + recog.base.match_token(BetweenExpr_T__0,&mut recog.err_handler)?; + } + } + + recog.base.set_state(36); + recog.base.match_token(BetweenExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule v*/ + recog.base.set_state(37); + recog.v_rec(0)?; + recog.base.set_state(38); + recog.base.match_token(BetweenExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule v*/ + recog.base.set_state(39); + recog.v_rec(0)?; + }} + BetweenExpr_T__4 |BetweenExpr_T__5 |BetweenExpr_T__6 => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + CmpContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(41); + _la = recog.base.input.la(1); + if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 224) != 0)) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(42); + recog.v_rec(0)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- v ---------------- pub type VContextAll<'input, 'arena, Tok = CommonToken<'input>> = VContext<'input, 'arena, Tok>; -pub type VContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, VContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct VContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for VContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::VContext } - fn get_rule_index(&self) -> usize { RULE_v } - fn make_node( - arena: &'arena Arena, - ctx: VContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a VContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => VContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut VContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut VContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> VContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, VContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { BetweenExprParserNodeKind, VContext, VContextExt, RULE_v } pub trait VContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1445,160 +982,99 @@ where } fn v_rec(&mut self, _p: i32) -> Result<&'arena VContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(VContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_v, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, VContext, RULE_v, 6, |_parentctx| VContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena VContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 6; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - { - /*InvokeRule atom*/ - recog.base.set_state(46); - recog.atom()?; - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(56); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(7)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(7,&mut recog.base)? } else { _sdp } }; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(54); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(6)?; _sdp } { - 1 =>{ - { - /*recRuleAltStartAction*/ - let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; - - recog.base.set_state(48); - if !({recog.precpred(None, 3)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; - } - recog.base.set_state(49); - _la = recog.base.input.la(1); - if { !(_la==BetweenExpr_T__7 || _la==BetweenExpr_T__8) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule v*/ - recog.base.set_state(50); - recog.v_rec(4)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + { + /*InvokeRule atom*/ + recog.base.set_state(46); + recog.atom()?; + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(56); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(7)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(7,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(54); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(6)?; _sdp } { + 1 =>{ + { + /*recRuleAltStartAction*/ + let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; + + recog.base.set_state(48); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleAltStartAction*/ - let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; - - recog.base.set_state(51); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(52); - _la = recog.base.input.la(1); - if { !(_la==BetweenExpr_T__9 || _la==BetweenExpr_T__10) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule v*/ - recog.base.set_state(53); - recog.v_rec(3)?; - } + recog.base.set_state(49); + _la = recog.base.input.la(1); + if { !(_la==BetweenExpr_T__7 || _la==BetweenExpr_T__8) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(50); + recog.v_rec(4)?; + } + } + , + 2 =>{ + { + /*recRuleAltStartAction*/ + let tmp = VContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_v)?; + + recog.base.set_state(51); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(52); + _la = recog.base.input.la(1); + if { !(_la==BetweenExpr_T__9 || _la==BetweenExpr_T__10) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule v*/ + recog.base.set_state(53); + recog.v_rec(3)?; } - - _ => {} } - } + + _ => {} } - recog.base.set_state(58); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(7)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(7,&mut recog.base)? } else { _sdp } }; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(58); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(7)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(7,&mut recog.base)? } else { _sdp } }; } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + } + }) } } //------------------- atom ---------------- pub type AtomContextAll<'input, 'arena, Tok = CommonToken<'input>> = AtomContext<'input, 'arena, Tok>; -pub type AtomContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AtomContextExt<'input, 'arena, Tok>, BetweenExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct AtomContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AtomContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = BetweenExprParserNodeKind; - fn node_tag() -> BetweenExprParserNodeKind { BetweenExprParserNodeKind::AtomContext } - fn get_rule_index(&self) -> usize { RULE_atom } - fn make_node( - arena: &'arena Arena, - ctx: AtomContext<'input, 'arena, Tok>, - ) -> *mut BetweenExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AtomContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AtomContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut BetweenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AtomContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AtomContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> AtomContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena BetweenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut BetweenExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, AtomContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { BetweenExprParserNodeKind, AtomContext, AtomContextExt, RULE_atom } pub trait AtomContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1640,75 +1116,60 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn atom(&mut self,) -> Result<&'arena AtomContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_atom)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, AtomContext, RULE_atom, 8, |_parentctx| AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena AtomContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(68); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(8)?; _sdp } { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(59); - recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; - } - } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - recog.base.set_state(60); - recog.base.match_token(BetweenExpr_INT,&mut recog.err_handler)?; - } + recog.base.set_state(68); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(8)?; _sdp } { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(59); + recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; } - , - 3 =>{ - /*------- Outer Most Alt 3 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } - { - recog.base.set_state(61); - recog.base.match_token(BetweenExpr_T__11,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(62); - recog.b_rec(0)?; - recog.base.set_state(63); - recog.base.match_token(BetweenExpr_T__12,&mut recog.err_handler)?; - } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(60); + recog.base.match_token(BetweenExpr_INT,&mut recog.err_handler)?; } - , - 4 =>{ - /*------- Outer Most Alt 4 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } - { - recog.base.set_state(65); - recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; - recog.base.set_state(66); - recog.base.match_token(BetweenExpr_T__13,&mut recog.err_handler)?; - /*InvokeRule b*/ - recog.base.set_state(67); - recog.b_rec(0)?; - } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(61); + recog.base.match_token(BetweenExpr_T__11,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(62); + recog.b_rec(0)?; + recog.base.set_state(63); + recog.base.match_token(BetweenExpr_T__12,&mut recog.err_handler)?; } - - _ => {} } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + , + 4 =>{ + /*------- Outer Most Alt 4 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } + { + recog.base.set_state(65); + recog.base.match_token(BetweenExpr_ID,&mut recog.err_handler)?; + recog.base.set_state(66); + recog.base.match_token(BetweenExpr_T__13,&mut recog.err_handler)?; + /*InvokeRule b*/ + recog.base.set_state(67); + recog.b_rec(0)?; + } } + + _ => {} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/csvlexer.rs b/runtime/Rust/tests/gen/csvlexer.rs index 076b70abbf..7d0106732e 100644 --- a/runtime/Rust/tests/gen/csvlexer.rs +++ b/runtime/Rust/tests/gen/csvlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -89,27 +72,7 @@ pub struct CSVLexerActions { impl CSVLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for CSVLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for CSVLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "CSVLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { CSVLexerActions, "CSVLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/csvparser.rs b/runtime/Rust/tests/gen/csvparser.rs index dae889368f..1ecf2da622 100644 --- a/runtime/Rust/tests/gen/csvparser.rs +++ b/runtime/Rust/tests/gen/csvparser.rs @@ -6,36 +6,11 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::csvlistener::*; use super::csvvisitor::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const CSV_T__0:i32=1; pub const CSV_T__1:i32=2; @@ -168,75 +143,13 @@ pub struct CSVParserExt<'input, 'arena> { impl<'input, 'arena> CSVParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for CSVParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_parser_recog! { CSVParserExt, CSVParserNodeKind, "CSV.g4" } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for CSVParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "CSV.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } -} //------------------- csvFile ---------------- pub type CsvFileContextAll<'input, 'arena, Tok = CommonToken<'input>> = CsvFileContext<'input, 'arena, Tok>; -pub type CsvFileContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, CsvFileContextExt<'input, 'arena, Tok>, CSVParserNodeKind, Tok>; dbt_antlr4::impl_visitable! { CSVVisitor::CsvFileContext(visit_csvFile) } -#[derive(Debug)] -pub struct CsvFileContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for CsvFileContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = CSVParserNodeKind; - fn node_tag() -> CSVParserNodeKind { CSVParserNodeKind::CsvFileContext } - fn get_rule_index(&self) -> usize { RULE_csvFile } - fn make_node( - arena: &'arena Arena, - ctx: CsvFileContext<'input, 'arena, Tok>, - ) -> *mut CSVParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a CSVParserNode<'input, 'arena, Tok>, - ) -> Option<&'a CsvFileContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => CsvFileContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut CSVParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut CsvFileContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut CsvFileContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> CsvFileContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena CSVParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut CSVParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, CsvFileContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { CSVParserNodeKind, CsvFileContext, CsvFileContextExt, RULE_csvFile } pub trait CsvFileContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -270,101 +183,40 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn csvFile(&mut self,) -> Result<&'arena CsvFileContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(CsvFileContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_csvFile)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, CsvFileContext, RULE_csvFile, 0, |_parentctx| CsvFileContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena CsvFileContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule hdr*/ + recog.base.set_state(8); + recog.hdr()?; + recog.base.set_state(10); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { { - /*InvokeRule hdr*/ - recog.base.set_state(8); - recog.hdr()?; - recog.base.set_state(10); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - loop { - { - { - /*InvokeRule row*/ - recog.base.set_state(9); - recog.row()?; - } - } - recog.base.set_state(12); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if !((((_la) & !0x3f) == 0 && ((1usize << _la) & 110) != 0)) {break} - } + { + /*InvokeRule row*/ + recog.base.set_state(9); + recog.row()?; } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; } + recog.base.set_state(12); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !((((_la) & !0x3f) == 0 && ((1usize << _la) & 110) != 0)) {break} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + } + }) } } //------------------- hdr ---------------- pub type HdrContextAll<'input, 'arena, Tok = CommonToken<'input>> = HdrContext<'input, 'arena, Tok>; -pub type HdrContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, HdrContextExt<'input, 'arena, Tok>, CSVParserNodeKind, Tok>; dbt_antlr4::impl_visitable! { CSVVisitor::HdrContext(visit_hdr) } -#[derive(Debug)] -pub struct HdrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for HdrContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = CSVParserNodeKind; - fn node_tag() -> CSVParserNodeKind { CSVParserNodeKind::HdrContext } - fn get_rule_index(&self) -> usize { RULE_hdr } - fn make_node( - arena: &'arena Arena, - ctx: HdrContext<'input, 'arena, Tok>, - ) -> *mut CSVParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a CSVParserNode<'input, 'arena, Tok>, - ) -> Option<&'a HdrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => HdrContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut CSVParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut HdrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut HdrContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> HdrContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena CSVParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut CSVParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, HdrContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { CSVParserNodeKind, HdrContext, HdrContextExt, RULE_hdr } pub trait HdrContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -390,84 +242,23 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn hdr(&mut self,) -> Result<&'arena HdrContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(HdrContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_hdr)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, HdrContext, RULE_hdr, 2, |_parentctx| HdrContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena HdrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule row*/ - recog.base.set_state(14); - recog.row()?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule row*/ + recog.base.set_state(14); + recog.row()?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- row ---------------- pub type RowContextAll<'input, 'arena, Tok = CommonToken<'input>> = RowContext<'input, 'arena, Tok>; -pub type RowContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, RowContextExt<'input, 'arena, Tok>, CSVParserNodeKind, Tok>; dbt_antlr4::impl_visitable! { CSVVisitor::RowContext(visit_row) } -#[derive(Debug)] -pub struct RowContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for RowContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = CSVParserNodeKind; - fn node_tag() -> CSVParserNodeKind { CSVParserNodeKind::RowContext } - fn get_rule_index(&self) -> usize { RULE_row } - fn make_node( - arena: &'arena Arena, - ctx: RowContext<'input, 'arena, Tok>, - ) -> *mut CSVParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a CSVParserNode<'input, 'arena, Tok>, - ) -> Option<&'a RowContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => RowContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut CSVParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut RowContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut RowContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> RowContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena CSVParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut CSVParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, RowContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { CSVParserNodeKind, RowContext, RowContextExt, RULE_row } pub trait RowContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -497,114 +288,53 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn row(&mut self,) -> Result<&'arena RowContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(RowContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_row)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, RowContext, RULE_row, 4, |_parentctx| RowContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena RowContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule field*/ + recog.base.set_state(16); + recog.field()?; + recog.base.set_state(21); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==CSV_T__0 { + { { + recog.base.set_state(17); + recog.base.match_token(CSV_T__0,&mut recog.err_handler)?; /*InvokeRule field*/ - recog.base.set_state(16); + recog.base.set_state(18); recog.field()?; - recog.base.set_state(21); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - while _la==CSV_T__0 { - { - { - recog.base.set_state(17); - recog.base.match_token(CSV_T__0,&mut recog.err_handler)?; - /*InvokeRule field*/ - recog.base.set_state(18); - recog.field()?; - } - } - recog.base.set_state(23); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); } - recog.base.set_state(25); + } + recog.base.set_state(23); recog.err_handler.sync(&mut recog.base)?; _la = recog.base.input.la(1); - if _la==CSV_T__1 { - { - recog.base.set_state(24); - recog.base.match_token(CSV_T__1,&mut recog.err_handler)?; - } + } + recog.base.set_state(25); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==CSV_T__1 { + { + recog.base.set_state(24); + recog.base.match_token(CSV_T__1,&mut recog.err_handler)?; } + } - recog.base.set_state(27); - recog.base.match_token(CSV_T__2,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(27); + recog.base.match_token(CSV_T__2,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- field ---------------- pub type FieldContextAll<'input, 'arena, Tok = CommonToken<'input>> = FieldContext<'input, 'arena, Tok>; -pub type FieldContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, FieldContextExt<'input, 'arena, Tok>, CSVParserNodeKind, Tok>; dbt_antlr4::impl_visitable! { CSVVisitor::FieldContext(visit_field) } -#[derive(Debug)] -pub struct FieldContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for FieldContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = CSVParserNodeKind; - fn node_tag() -> CSVParserNodeKind { CSVParserNodeKind::FieldContext } - fn get_rule_index(&self) -> usize { RULE_field } - fn make_node( - arena: &'arena Arena, - ctx: FieldContext<'input, 'arena, Tok>, - ) -> *mut CSVParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a CSVParserNode<'input, 'arena, Tok>, - ) -> Option<&'a FieldContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => FieldContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut CSVParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut FieldContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut FieldContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> FieldContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena CSVParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut CSVParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, FieldContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { CSVParserNodeKind, FieldContext, FieldContextExt, RULE_field } pub trait FieldContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -642,48 +372,33 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn field(&mut self,) -> Result<&'arena FieldContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(FieldContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_field)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, FieldContext, RULE_field, 6, |_parentctx| FieldContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena FieldContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(32); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - CSV_TEXT => { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(29); - recog.base.match_token(CSV_TEXT,&mut recog.err_handler)?; - }} - CSV_STRING => { - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - recog.base.set_state(30); - recog.base.match_token(CSV_STRING,&mut recog.err_handler)?; - }} - CSV_T__0 |CSV_T__1 |CSV_T__2 => { - /*------- Outer Most Alt 3 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } - { - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + CSV_TEXT => { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(29); + recog.base.match_token(CSV_TEXT,&mut recog.err_handler)?; + }} + CSV_STRING => { + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(30); + recog.base.match_token(CSV_STRING,&mut recog.err_handler)?; + }} + CSV_T__0 |CSV_T__1 |CSV_T__2 => { + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/fuzzexprlexer.rs b/runtime/Rust/tests/gen/fuzzexprlexer.rs index 60aec0da14..296a32224f 100644 --- a/runtime/Rust/tests/gen/fuzzexprlexer.rs +++ b/runtime/Rust/tests/gen/fuzzexprlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -103,27 +86,7 @@ pub struct FuzzExprLexerActions { impl FuzzExprLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for FuzzExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for FuzzExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "FuzzExprLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { FuzzExprLexerActions, "FuzzExprLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/fuzzexprparser.rs b/runtime/Rust/tests/gen/fuzzexprparser.rs index 1774575b22..f84e26459c 100644 --- a/runtime/Rust/tests/gen/fuzzexprparser.rs +++ b/runtime/Rust/tests/gen/fuzzexprparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::fuzzexprlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const FuzzExpr_T__0:i32=1; pub const FuzzExpr_T__1:i32=2; @@ -177,32 +152,7 @@ pub struct FuzzExprParserExt<'input, 'arena> { impl<'input, 'arena> FuzzExprParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for FuzzExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for FuzzExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "FuzzExpr.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena FuzzExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 4 => FuzzExprParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { FuzzExprParserExt, FuzzExprParserNodeKind, "FuzzExpr.g4"; sempred (FuzzExprParserNode<'input, 'arena, TF::Tok>, FuzzExprParser) { 4 => e_sempred, } } impl<'input, 'arena, Input, TF> FuzzExprParser<'input, 'arena, Input, TF> where @@ -232,53 +182,7 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -316,113 +220,52 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule item*/ + recog.base.set_state(12); + recog.item()?; + recog.base.set_state(17); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==FuzzExpr_T__0 { + { { + recog.base.set_state(13); + recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; /*InvokeRule item*/ - recog.base.set_state(12); + recog.base.set_state(14); recog.item()?; - recog.base.set_state(17); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - while _la==FuzzExpr_T__0 { - { - { - recog.base.set_state(13); - recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule item*/ - recog.base.set_state(14); - recog.item()?; - } - } - recog.base.set_state(19); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); } - recog.base.set_state(21); + } + recog.base.set_state(19); recog.err_handler.sync(&mut recog.base)?; _la = recog.base.input.la(1); - if _la==FuzzExpr_T__1 { - { - recog.base.set_state(20); - recog.base.match_token(FuzzExpr_T__1,&mut recog.err_handler)?; - } + } + recog.base.set_state(21); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==FuzzExpr_T__1 { + { + recog.base.set_state(20); + recog.base.match_token(FuzzExpr_T__1,&mut recog.err_handler)?; } + } - recog.base.set_state(23); - recog.base.match_token(FuzzExpr_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(23); + recog.base.match_token(FuzzExpr_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- item ---------------- pub type ItemContextAll<'input, 'arena, Tok = CommonToken<'input>> = ItemContext<'input, 'arena, Tok>; -pub type ItemContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ItemContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct ItemContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ItemContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::ItemContext } - fn get_rule_index(&self) -> usize { RULE_item } - fn make_node( - arena: &'arena Arena, - ctx: ItemContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ItemContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ItemContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ItemContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ItemContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> ItemContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, ItemContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, ItemContext, ItemContextExt, RULE_item } pub trait ItemContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -452,289 +295,228 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn item(&mut self,) -> Result<&'arena ItemContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(ItemContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_item)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, ItemContext, RULE_item, 2, |_parentctx| ItemContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena ItemContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(30); - recog.err_handler.sync(&mut recog.base)?; - match { let _m = recog.base.dfa_predict_mask(2)?; - match _m { - 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_T__6 | FuzzExpr_T__11 | FuzzExpr_ID | FuzzExpr_INT].contains(&recog.input.la(1)) => { - recog.base.set_state(25); - let _neutral_state = recog.base.begin_neutral_parse(0); - match recog.e() { - Err(e) if !e.is_recoverable() => { - recog.base.end_neutral_parse(&_neutral_state); - return Err(e) - }, - Err(_) => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - }, - Ok(_node) => { - if recog.base.syntax_error_count() != _neutral_state.2 { - recog.base.end_neutral_parse(&_neutral_state); - // errorful neutral parse: throw its result away and - // defer (muted, so no spurious reports escaped) - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - } - else { - // the tail token decides on the post-prefix stream. - // An explicit arm (or the static default) rewinds into - // resume mode; anything else rewinds and defers to the - // adaptive engine from the decision start - no resume, - // the chosen body re-parses everything - let _tailbit = { let _t = recog.input.la(1); match _t { - FuzzExpr_T__2 if !false || !recog.base.follow_contains(_t) => Some(0x1), - _ => Some(0x2), - } }; - match _tailbit { - Some(bit) => { - recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e); - recog.base.end_neutral_parse(&_neutral_state); - bit - } - None => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - } - } - } - }, - } - }, - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_T__11 | FuzzExpr_ID | FuzzExpr_INT].contains(&recog.input.la(1)) => { - recog.base.set_state(45); - let _neutral_state = recog.base.begin_neutral_parse(0); - match recog.atom() { - Err(e) if !e.is_recoverable() => { - recog.base.end_neutral_parse(&_neutral_state); - return Err(e) - }, - Err(_) => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - }, - Ok(_node) => { - if recog.base.syntax_error_count() != _neutral_state.2 { - recog.base.end_neutral_parse(&_neutral_state); - // errorful neutral parse: throw its result away and - // defer (muted, so no spurious reports escaped) - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - } - else { - // the tail token decides on the post-prefix stream. - // An explicit arm (or the static default) rewinds into - // resume mode; anything else rewinds and defers to the - // adaptive engine from the decision start - no resume, - // the chosen body re-parses everything - let _tailbit = { let _t = recog.input.la(1); match _t { - FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), - _ => None, - } }; - match _tailbit { - Some(bit) => { - recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_atom); - recog.base.end_neutral_parse(&_neutral_state); - bit - } - None => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - } - } - } - }, - } - }, - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_ID].contains(&recog.input.la(1)) => { - recog.base.set_state(67); - let _neutral_state = recog.base.begin_neutral_parse(0); - match recog.q() { - Err(e) if !e.is_recoverable() => { - recog.base.end_neutral_parse(&_neutral_state); - return Err(e) - }, - Err(_) => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - }, - Ok(_node) => { - if recog.base.syntax_error_count() != _neutral_state.2 { - recog.base.end_neutral_parse(&_neutral_state); - // errorful neutral parse: throw its result away and - // defer (muted, so no spurious reports escaped) - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - } - else { - // the tail token decides on the post-prefix stream. - // An explicit arm (or the static default) rewinds into - // resume mode; anything else rewinds and defers to the - // adaptive engine from the decision start - no resume, - // the chosen body re-parses everything - let _tailbit = { let _t = recog.input.la(1); match _t { - FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), - _ => None, - } }; - match _tailbit { - Some(bit) => { - recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_q); - recog.base.end_neutral_parse(&_neutral_state); - bit - } - None => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - } - } - } - }, - } - }, - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_ID].contains(&recog.input.la(1)) => { - recog.base.set_state(34); - let _neutral_state = recog.base.begin_neutral_parse(0); - match recog.name() { - Err(e) if !e.is_recoverable() => { - recog.base.end_neutral_parse(&_neutral_state); - return Err(e) - }, - Err(_) => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - }, - Ok(_node) => { - if recog.base.syntax_error_count() != _neutral_state.2 { - recog.base.end_neutral_parse(&_neutral_state); - // errorful neutral parse: throw its result away and - // defer (muted, so no spurious reports escaped) - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - } - else { - // the tail token decides on the post-prefix stream. - // An explicit arm (or the static default) rewinds into - // resume mode; anything else rewinds and defers to the - // adaptive engine from the decision start - no resume, - // the chosen body re-parses everything - let _tailbit = { let _t = recog.input.la(1); match _t { - FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), - _ => None, - } }; - match _tailbit { - Some(bit) => { - recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_name); - recog.base.end_neutral_parse(&_neutral_state); - bit - } - None => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) - } - } - } - }, - } - }, - x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), - x if (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), - m => m, - } } { - x if x == 0x1 =>{ - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule e*/ - recog.base.set_state(25); - recog.e_rec(0)?; - recog.base.set_state(26); - recog.base.match_token(FuzzExpr_T__2,&mut recog.err_handler)?; - /*InvokeRule name*/ - recog.base.set_state(27); - recog.name()?; - } - }, - x if x == 0x2 =>{ - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - /*InvokeRule e*/ - recog.base.set_state(29); - recog.e_rec(0)?; - } - } - _ => {} + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + match { let _m = recog.base.dfa_predict_mask(2)?; + match _m { + 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_T__6 | FuzzExpr_T__11 | FuzzExpr_ID | FuzzExpr_INT].contains(&recog.input.la(1)) => { + recog.base.set_state(25); + let _neutral_state = recog.base.begin_neutral_parse(0); + match recog.e() { + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, + Err(_) => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything + let _tailbit = { let _t = recog.input.la(1); match _t { + FuzzExpr_T__2 if !false || !recog.base.follow_contains(_t) => Some(0x1), + _ => Some(0x2), + } }; + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + } + } + }, + } + }, + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_T__11 | FuzzExpr_ID | FuzzExpr_INT].contains(&recog.input.la(1)) => { + recog.base.set_state(45); + let _neutral_state = recog.base.begin_neutral_parse(0); + match recog.atom() { + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, + Err(_) => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything + let _tailbit = { let _t = recog.input.la(1); match _t { + FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), + _ => None, + } }; + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_atom); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + } + } + }, + } + }, + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_ID].contains(&recog.input.la(1)) => { + recog.base.set_state(67); + let _neutral_state = recog.base.begin_neutral_parse(0); + match recog.q() { + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, + Err(_) => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything + let _tailbit = { let _t = recog.input.la(1); match _t { + FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), + _ => None, + } }; + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_q); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + } + } + }, + } + }, + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [FuzzExpr_T__2 | FuzzExpr_ID].contains(&recog.input.la(1)) => { + recog.base.set_state(34); + let _neutral_state = recog.base.begin_neutral_parse(0); + match recog.name() { + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, + Err(_) => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything + let _tailbit = { let _t = recog.input.la(1); match _t { + FuzzExpr_T__2 if !true || !recog.base.follow_contains(_t) => Some(0x1), + _ => None, + } }; + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_name); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32) + } + } + } + }, + } + }, + x if x != 0 && (x & !0x3) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + x if (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(2,&mut recog.base)? - 1) as u32), + m => m, + } } { + x if x == 0x1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(25); + recog.e_rec(0)?; + recog.base.set_state(26); + recog.base.match_token(FuzzExpr_T__2,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(27); + recog.name()?; } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + }, + x if x == 0x2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + /*InvokeRule e*/ + recog.base.set_state(29); + recog.e_rec(0)?; } } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + _ => {} + } + }) } } //------------------- name ---------------- pub type NameContextAll<'input, 'arena, Tok = CommonToken<'input>> = NameContext<'input, 'arena, Tok>; -pub type NameContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NameContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct NameContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for NameContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::NameContext } - fn get_rule_index(&self) -> usize { RULE_name } - fn make_node( - arena: &'arena Arena, - ctx: NameContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NameContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => NameContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NameContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut NameContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> NameContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, NameContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, NameContext, NameContextExt, RULE_name } pub trait NameContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -767,91 +549,30 @@ where if let Some(_node) = self.base.resume_take(RULE_name)? { return Ok(_node.as_rule_context().unwrap()); } - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_name)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, NameContext, RULE_name, 4, |_parentctx| NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena NameContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(32); - _la = recog.base.input.la(1); - if { !(_la==FuzzExpr_T__2 || _la==FuzzExpr_ID) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__2 || _la==FuzzExpr_ID) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + } + }) } } //------------------- q ---------------- pub type QContextAll<'input, 'arena, Tok = CommonToken<'input>> = QContext<'input, 'arena, Tok>; -pub type QContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, QContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct QContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for QContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: QContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a QContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => QContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut QContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut QContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, QContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, QContext, QContextExt, RULE_q } pub trait QContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -884,103 +605,42 @@ where if let Some(_node) = self.base.resume_take(RULE_q)? { return Ok(_node.as_rule_context().unwrap()); } - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(QContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_q)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, QContext, RULE_q, 6, |_parentctx| QContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena QContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule name*/ - recog.base.set_state(34); - recog.name()?; - recog.base.set_state(39); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - { - { - recog.base.set_state(35); - recog.base.match_token(FuzzExpr_T__3,&mut recog.err_handler)?; - /*InvokeRule name*/ - recog.base.set_state(36); - recog.name()?; - } - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule name*/ + recog.base.set_state(34); + recog.name()?; + recog.base.set_state(39); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + { + { + recog.base.set_state(35); + recog.base.match_token(FuzzExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule name*/ + recog.base.set_state(36); + recog.name()?; } - recog.base.set_state(41); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; - } - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + } } + recog.base.set_state(41); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + } + }) } } //------------------- e ---------------- pub type EContextAll<'input, 'arena, Tok = CommonToken<'input>> = EContext<'input, 'arena, Tok>; -pub type EContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, EContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: EContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, EContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, EContext, EContextExt, RULE_e } pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1022,212 +682,151 @@ where if let Some(_node) = self.base.resume_take(RULE_e)? { return Ok(_node.as_rule_context().unwrap()); } - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_e, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, EContext, RULE_e, 8, |_parentctx| EContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 8; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(46); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - FuzzExpr_T__6 => { - { - recog.base.set_state(43); - recog.base.match_token(FuzzExpr_T__6,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(44); - recog.e_rec(5)?; - }} - FuzzExpr_T__2 |FuzzExpr_T__11 |FuzzExpr_ID |FuzzExpr_INT => { - { - /*InvokeRule atom*/ - recog.base.set_state(45); - recog.atom()?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(64); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } }; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(62); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(5)?; _sdp } { - 1 =>{ - { - /*recRuleAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(46); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + FuzzExpr_T__6 => { + { + recog.base.set_state(43); + recog.base.match_token(FuzzExpr_T__6,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(44); + recog.e_rec(5)?; + }} + FuzzExpr_T__2 |FuzzExpr_T__11 |FuzzExpr_ID |FuzzExpr_INT => { + { + /*InvokeRule atom*/ + recog.base.set_state(45); + recog.atom()?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(64); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(62); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(5)?; _sdp } { + 1 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - recog.base.set_state(48); - if !({recog.precpred(None, 4)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; - } - recog.base.set_state(49); - recog.base.match_token(FuzzExpr_T__7,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(50); - recog.e_rec(4)?; - } + recog.base.set_state(48); + if !({recog.precpred(None, 4)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - - recog.base.set_state(51); - if !({recog.precpred(None, 3)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; - } - recog.base.set_state(52); - _la = recog.base.input.la(1); - if { !(_la==FuzzExpr_T__8 || _la==FuzzExpr_T__9) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(53); - recog.e_rec(4)?; - } + recog.base.set_state(49); + recog.base.match_token(FuzzExpr_T__7,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(50); + recog.e_rec(4)?; } - , - 3 =>{ - { - /*recRuleAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + } + , + 2 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - recog.base.set_state(54); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(55); - _la = recog.base.input.la(1); - if { !(_la==FuzzExpr_T__6 || _la==FuzzExpr_T__10) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(56); - recog.e_rec(3)?; - } + recog.base.set_state(51); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(52); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__8 || _la==FuzzExpr_T__9) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; } - , - 4 =>{ - { - /*recRuleAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; + /*InvokeRule e*/ + recog.base.set_state(53); + recog.e_rec(4)?; + } + } + , + 3 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - recog.base.set_state(57); - if !({recog.precpred(None, 6)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; - } - recog.base.set_state(58); - recog.base.match_token(FuzzExpr_T__4,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(59); - recog.e_rec(0)?; - recog.base.set_state(60); - recog.base.match_token(FuzzExpr_T__5,&mut recog.err_handler)?; - } + recog.base.set_state(54); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(55); + _la = recog.base.input.la(1); + if { !(_la==FuzzExpr_T__6 || _la==FuzzExpr_T__10) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; } + /*InvokeRule e*/ + recog.base.set_state(56); + recog.e_rec(3)?; + } + } + , + 4 =>{ + { + /*recRuleAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_e)?; - _ => {} + recog.base.set_state(57); + if !({recog.precpred(None, 6)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; + } + recog.base.set_state(58); + recog.base.match_token(FuzzExpr_T__4,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(59); + recog.e_rec(0)?; + recog.base.set_state(60); + recog.base.match_token(FuzzExpr_T__5,&mut recog.err_handler)?; + } } - } + + _ => {} } - recog.base.set_state(66); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } }; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(66); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(6)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(6,&mut recog.base)? } else { _sdp } }; + } } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + }) } } //------------------- atom ---------------- pub type AtomContextAll<'input, 'arena, Tok = CommonToken<'input>> = AtomContext<'input, 'arena, Tok>; -pub type AtomContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AtomContextExt<'input, 'arena, Tok>, FuzzExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct AtomContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AtomContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = FuzzExprParserNodeKind; - fn node_tag() -> FuzzExprParserNodeKind { FuzzExprParserNodeKind::AtomContext } - fn get_rule_index(&self) -> usize { RULE_atom } - fn make_node( - arena: &'arena Arena, - ctx: AtomContext<'input, 'arena, Tok>, - ) -> *mut FuzzExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AtomContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AtomContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut FuzzExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AtomContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AtomContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> AtomContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena FuzzExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut FuzzExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, AtomContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { FuzzExprParserNodeKind, AtomContext, AtomContextExt, RULE_atom } pub trait AtomContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1280,104 +879,89 @@ where if let Some(_node) = self.base.resume_take(RULE_atom)? { return Ok(_node.as_rule_context().unwrap()); } - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 10, RULE_atom)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, AtomContext, RULE_atom, 10, |_parentctx| AtomContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena AtomContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(86); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(9)?; _sdp } { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule q*/ - recog.base.set_state(67); - recog.q()?; - } + recog.base.set_state(86); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(9)?; _sdp } { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule q*/ + recog.base.set_state(67); + recog.q()?; } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - recog.base.set_state(68); - recog.base.match_token(FuzzExpr_INT,&mut recog.err_handler)?; - } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(68); + recog.base.match_token(FuzzExpr_INT,&mut recog.err_handler)?; + } + } + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(69); + recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(70); + recog.e_rec(0)?; + recog.base.set_state(71); + recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; } - , - 3 =>{ - /*------- Outer Most Alt 3 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + } + , + 4 =>{ + /*------- Outer Most Alt 4 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } + { + recog.base.set_state(73); + recog.base.match_token(FuzzExpr_ID,&mut recog.err_handler)?; + recog.base.set_state(74); + recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; + recog.base.set_state(83); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if (((_la) & !0x3f) == 0 && ((1usize << _la) & 53384) != 0) { { - recog.base.set_state(69); - recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; /*InvokeRule e*/ - recog.base.set_state(70); + recog.base.set_state(75); recog.e_rec(0)?; - recog.base.set_state(71); - recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; - } - } - , - 4 =>{ - /*------- Outer Most Alt 4 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(4); } - { - recog.base.set_state(73); - recog.base.match_token(FuzzExpr_ID,&mut recog.err_handler)?; - recog.base.set_state(74); - recog.base.match_token(FuzzExpr_T__11,&mut recog.err_handler)?; - recog.base.set_state(83); + recog.base.set_state(80); recog.err_handler.sync(&mut recog.base)?; _la = recog.base.input.la(1); - if (((_la) & !0x3f) == 0 && ((1usize << _la) & 53384) != 0) { + while _la==FuzzExpr_T__0 { { + { + recog.base.set_state(76); + recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; /*InvokeRule e*/ - recog.base.set_state(75); + recog.base.set_state(77); recog.e_rec(0)?; - recog.base.set_state(80); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - while _la==FuzzExpr_T__0 { - { - { - recog.base.set_state(76); - recog.base.match_token(FuzzExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(77); - recog.e_rec(0)?; - } - } - recog.base.set_state(82); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); } } + recog.base.set_state(82); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); } - - recog.base.set_state(85); - recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; } } - _ => {} - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + recog.base.set_state(85); + recog.base.match_token(FuzzExpr_T__12,&mut recog.err_handler)?; + } } + + _ => {} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/guardexprlexer.rs b/runtime/Rust/tests/gen/guardexprlexer.rs index 31533c85cb..c605be0686 100644 --- a/runtime/Rust/tests/gen/guardexprlexer.rs +++ b/runtime/Rust/tests/gen/guardexprlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -100,27 +83,7 @@ pub struct GuardExprLexerActions { impl GuardExprLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for GuardExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for GuardExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "GuardExprLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { GuardExprLexerActions, "GuardExprLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/guardexprparser.rs b/runtime/Rust/tests/gen/guardexprparser.rs index b3cb3b943d..e95ed99351 100644 --- a/runtime/Rust/tests/gen/guardexprparser.rs +++ b/runtime/Rust/tests/gen/guardexprparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::guardexprlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const GuardExpr_T__0:i32=1; pub const GuardExpr_T__1:i32=2; @@ -172,32 +147,7 @@ pub struct GuardExprParserExt<'input, 'arena> { impl<'input, 'arena> GuardExprParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for GuardExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for GuardExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "GuardExpr.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena GuardExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 2 => GuardExprParser::<'input, 'arena, Input, TF>::expr_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { GuardExprParserExt, GuardExprParserNodeKind, "GuardExpr.g4"; sempred (GuardExprParserNode<'input, 'arena, TF::Tok>, GuardExprParser) { 2 => expr_sempred, } } impl<'input, 'arena, Input, TF> GuardExprParser<'input, 'arena, Input, TF> where @@ -221,53 +171,7 @@ where //------------------- prog ---------------- pub type ProgContextAll<'input, 'arena, Tok = CommonToken<'input>> = ProgContext<'input, 'arena, Tok>; -pub type ProgContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ProgContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct ProgContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ProgContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ProgContext } - fn get_rule_index(&self) -> usize { RULE_prog } - fn make_node( - arena: &'arena Arena, - ctx: ProgContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ProgContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ProgContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ProgContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ProgContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> ProgContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, ProgContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { GuardExprParserNodeKind, ProgContext, ProgContextExt, RULE_prog } pub trait ProgContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -305,47 +209,32 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn prog(&mut self,) -> Result<&'arena ProgContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(ProgContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_prog)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, ProgContext, RULE_prog, 0, |_parentctx| ProgContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena ProgContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(11); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { { - recog.base.set_state(11); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - loop { - { - { - /*InvokeRule stmt*/ - recog.base.set_state(10); - recog.stmt()?; - } - } - recog.base.set_state(13); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if !((((_la) & !0x3f) == 0 && ((1usize << _la) & 13330) != 0)) {break} - } - recog.base.set_state(15); - recog.base.match_token(GuardExpr_EOF,&mut recog.err_handler)?; + { + /*InvokeRule stmt*/ + recog.base.set_state(10); + recog.stmt()?; } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; } + recog.base.set_state(13); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !((((_la) & !0x3f) == 0 && ((1usize << _la) & 13330) != 0)) {break} + } + recog.base.set_state(15); + recog.base.match_token(GuardExpr_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- stmt ---------------- @@ -389,39 +278,7 @@ pub struct StmtContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for StmtContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } - fn get_rule_index(&self) -> usize { RULE_stmt } - fn make_node( - arena: &'arena Arena, - ctx: StmtContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StmtContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a StmtContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => StmtContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut StmtContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut StmtContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled GuardExprParserNodeKind::StmtContext, StmtContextAll, StmtContextExt, RULE_stmt } impl<'input: 'arena, 'arena, Tok: Token + 'input> StmtContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -431,7 +288,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> StmtContextExt<'input, 'arena, ) } } - pub trait StmtContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -467,42 +323,7 @@ pub struct EvalContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for EvalContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } - fn get_rule_index(&self) -> usize { RULE_stmt } - fn make_node( - arena: &'arena Arena, - ctx: EvalContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StmtContextAll::EvalContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a EvalContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => StmtContextAll<'input, 'arena, Tok>) { - StmtContextAll::EvalContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut EvalContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut StmtContextAll<'input, 'arena, Tok>) { - StmtContextAll::EvalContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::StmtContext, StmtContextAll::EvalContext, EvalContextExt, RULE_stmt } impl<'input, 'arena, Tok> StmtContextAttrs<'input, 'arena, Tok> for EvalContext<'input, 'arena, Tok> where @@ -567,42 +388,7 @@ pub struct AssignContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AssignContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::StmtContext } - fn get_rule_index(&self) -> usize { RULE_stmt } - fn make_node( - arena: &'arena Arena, - ctx: AssignContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StmtContextAll::AssignContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AssignContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => StmtContextAll<'input, 'arena, Tok>) { - StmtContextAll::AssignContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AssignContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut StmtContextAll<'input, 'arena, Tok>) { - StmtContextAll::AssignContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::StmtContext, StmtContextAll::AssignContext, AssignContextExt, RULE_stmt } impl<'input, 'arena, Tok> StmtContextAttrs<'input, 'arena, Tok> for AssignContext<'input, 'arena, Tok> where @@ -648,64 +434,49 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn stmt(&mut self,) -> Result<&'arena StmtContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(StmtContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_stmt)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, StmtContext, RULE_stmt, 2, |_parentctx| StmtContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena StmtContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(26); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - GuardExpr_T__0 => { - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - AssignContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena AssignContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(17); - recog.base.match_token(GuardExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(18); - recog.expr_rec(0)?; - recog.base.set_state(19); - recog.base.match_token(GuardExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(20); - recog.expr_rec(0)?; - recog.base.set_state(21); - recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; - }} - GuardExpr_T__3 |GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - EvalContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena EvalContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - /*InvokeRule expr*/ - recog.base.set_state(23); - recog.expr_rec(0)?; - recog.base.set_state(24); - recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(26); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__0 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + AssignContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena AssignContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(17); + recog.base.match_token(GuardExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(18); + recog.expr_rec(0)?; + recog.base.set_state(19); + recog.base.match_token(GuardExpr_T__1,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(20); + recog.expr_rec(0)?; + recog.base.set_state(21); + recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; + }} + GuardExpr_T__3 |GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + EvalContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena EvalContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + /*InvokeRule expr*/ + recog.base.set_state(23); + recog.expr_rec(0)?; + recog.base.set_state(24); + recog.base.match_token(GuardExpr_T__2,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- expr ---------------- @@ -753,39 +524,7 @@ pub struct ExprContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ExprContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: ExprContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ExprContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ExprContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ExprContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ExprContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled GuardExprParserNodeKind::ExprContext, ExprContextAll, ExprContextExt, RULE_expr } impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -795,7 +534,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, ) } } - pub trait ExprContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -831,42 +569,7 @@ pub struct NotContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NotContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: NotContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::NotContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NotContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::NotContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NotContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::NotContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::ExprContext, ExprContextAll::NotContext, NotContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for NotContext<'input, 'arena, Tok> where @@ -931,42 +634,7 @@ pub struct PredicatedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Co pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PredicatedContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: PredicatedContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::PredicatedContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PredicatedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::PredicatedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PredicatedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::PredicatedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::ExprContext, ExprContextAll::PredicatedContext, PredicatedContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for PredicatedContext<'input, 'arena, Tok> where @@ -1031,42 +699,7 @@ pub struct OrContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToke pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for OrContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: OrContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::OrContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a OrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::OrContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut OrContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::OrContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::ExprContext, ExprContextAll::OrContext, OrContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for OrContext<'input, 'arena, Tok> where @@ -1131,42 +764,7 @@ pub struct AndContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AndContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: AndContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::AndContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AndContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::AndContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AndContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::AndContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::ExprContext, ExprContextAll::AndContext, AndContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for AndContext<'input, 'arena, Tok> where @@ -1217,127 +815,112 @@ where } fn expr_rec(&mut self, _p: i32) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_expr, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, ExprContext, RULE_expr, 4, |_parentctx| ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena ExprContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 4; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(35); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { - { - recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - /*InvokeRule value*/ - recog.base.set_state(29); - recog.value()?; - recog.base.set_state(31); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } } { - x if x == 1 =>{ - { - /*InvokeRule pred*/ - recog.base.set_state(30); - recog.pred()?; - } - } - - _ => {} - } - }} - GuardExpr_T__3 => { - { - recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(33); - recog.base.match_token(GuardExpr_T__3,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(34); - recog.expr_rec(3)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(45); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } }; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(43); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(4)?; _sdp } { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AndContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(37); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(38); - recog.base.match_token(GuardExpr_T__4,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(39); - recog.expr_rec(3)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(35); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__9 |GuardExpr_ID |GuardExpr_INT => { + { + recog.base.with_mut_ctx(|ctx| { PredicatedContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena PredicatedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + /*InvokeRule value*/ + recog.base.set_state(29); + recog.value()?; + recog.base.set_state(31); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } } { + x if x == 1 =>{ + { + /*InvokeRule pred*/ + recog.base.set_state(30); + recog.pred()?; + } + } + + _ => {} + } + }} + GuardExpr_T__3 => { + { + recog.base.with_mut_ctx(|ctx| { NotContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NotContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(33); + recog.base.match_token(GuardExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(34); + recog.expr_rec(3)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(45); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(4)?; _sdp } { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AndContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AndContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(37); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - OrContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; - let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(40); - if !({recog.precpred(None, 1)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; - } - recog.base.set_state(41); - recog.base.match_token(GuardExpr_T__5,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(42); - recog.expr_rec(2)?; - } + recog.base.set_state(38); + recog.base.match_token(GuardExpr_T__4,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(39); + recog.expr_rec(3)?; + } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + OrContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena OrContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(40); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(41); + recog.base.match_token(GuardExpr_T__5,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(42); + recog.expr_rec(2)?; } - - _ => {} } - } + + _ => {} } - recog.base.set_state(47); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } }; - } + } } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(47); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(5)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(5,&mut recog.base)? } else { _sdp } }; + } } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + }) } } //------------------- pred ---------------- @@ -1381,39 +964,7 @@ pub struct PredContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PredContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: PredContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PredContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PredContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PredContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PredContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled GuardExprParserNodeKind::PredContext, PredContextAll, PredContextExt, RULE_pred } impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -1423,7 +974,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> PredContextExt<'input, 'arena, ) } } - pub trait PredContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -1459,42 +1009,7 @@ pub struct CmpContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CmpContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: CmpContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::CmpContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a CmpContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { - PredContextAll::CmpContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut CmpContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { - PredContextAll::CmpContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::PredContext, PredContextAll::CmpContext, CmpContextExt, RULE_pred } impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for CmpContext<'input, 'arena, Tok> where @@ -1555,42 +1070,7 @@ pub struct InListContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for InListContextExt<'input, 'arena, Tok> -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::PredContext } - fn get_rule_index(&self) -> usize { RULE_pred } - fn make_node( - arena: &'arena Arena, - ctx: InListContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(PredContextAll::InListContext(ctx)) - } - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a InListContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => PredContextAll<'input, 'arena, Tok>) { - PredContextAll::InListContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut InListContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut PredContextAll<'input, 'arena, Tok>) { - PredContextAll::InListContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt GuardExprParserNodeKind::PredContext, PredContextAll::InListContext, InListContextExt, RULE_pred } impl<'input, 'arena, Tok> PredContextAttrs<'input, 'arena, Tok> for InListContext<'input, 'arena, Tok> where @@ -1636,122 +1116,61 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn pred(&mut self,) -> Result<&'arena PredContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_pred)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, PredContext, RULE_pred, 6, |_parentctx| PredContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena PredContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(55); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - GuardExpr_T__1 |GuardExpr_T__6 |GuardExpr_T__7 => { - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - CmpContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(48); - _la = recog.base.input.la(1); - if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 388) != 0)) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule value*/ - recog.base.set_state(49); - recog.value()?; - }} - GuardExpr_T__8 => { - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - InListContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena InListContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(50); - recog.base.match_token(GuardExpr_T__8,&mut recog.err_handler)?; - recog.base.set_state(51); - recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(52); - recog.expr_rec(0)?; - recog.base.set_state(53); - recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(55); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_T__1 |GuardExpr_T__6 |GuardExpr_T__7 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + CmpContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CmpContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(48); + _la = recog.base.input.la(1); + if { !((((_la) & !0x3f) == 0 && ((1usize << _la) & 388) != 0)) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule value*/ + recog.base.set_state(49); + recog.value()?; + }} + GuardExpr_T__8 => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + InListContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena InListContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(50); + recog.base.match_token(GuardExpr_T__8,&mut recog.err_handler)?; + recog.base.set_state(51); + recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(52); + recog.expr_rec(0)?; + recog.base.set_state(53); + recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- value ---------------- pub type ValueContextAll<'input, 'arena, Tok = CommonToken<'input>> = ValueContext<'input, 'arena, Tok>; -pub type ValueContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, ValueContextExt<'input, 'arena, Tok>, GuardExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct ValueContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ValueContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = GuardExprParserNodeKind; - fn node_tag() -> GuardExprParserNodeKind { GuardExprParserNodeKind::ValueContext } - fn get_rule_index(&self) -> usize { RULE_value } - fn make_node( - arena: &'arena Arena, - ctx: ValueContext<'input, 'arena, Tok>, - ) -> *mut GuardExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ValueContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ValueContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut GuardExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ValueContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ValueContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> ValueContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena GuardExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut GuardExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, ValueContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { GuardExprParserNodeKind, ValueContext, ValueContextExt, RULE_value } pub trait ValueContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1793,55 +1212,40 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn value(&mut self,) -> Result<&'arena ValueContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(ValueContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_value)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, ValueContext, RULE_value, 8, |_parentctx| ValueContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena ValueContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(63); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - GuardExpr_ID => { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(57); - recog.base.match_token(GuardExpr_ID,&mut recog.err_handler)?; - }} - GuardExpr_INT => { - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - recog.base.set_state(58); - recog.base.match_token(GuardExpr_INT,&mut recog.err_handler)?; - }} - GuardExpr_T__9 => { - /*------- Outer Most Alt 3 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } - { - recog.base.set_state(59); - recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; - /*InvokeRule expr*/ - recog.base.set_state(60); - recog.expr_rec(0)?; - recog.base.set_state(61); - recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(63); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + GuardExpr_ID => { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(57); + recog.base.match_token(GuardExpr_ID,&mut recog.err_handler)?; + }} + GuardExpr_INT => { + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(58); + recog.base.match_token(GuardExpr_INT,&mut recog.err_handler)?; + }} + GuardExpr_T__9 => { + /*------- Outer Most Alt 3 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(3); } + { + recog.base.set_state(59); + recog.base.match_token(GuardExpr_T__9,&mut recog.err_handler)?; + /*InvokeRule expr*/ + recog.base.set_state(60); + recog.expr_rec(0)?; + recog.base.set_state(61); + recog.base.match_token(GuardExpr_T__10,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/labelslexer.rs b/runtime/Rust/tests/gen/labelslexer.rs index 440d9efcdb..7b28d02fd9 100644 --- a/runtime/Rust/tests/gen/labelslexer.rs +++ b/runtime/Rust/tests/gen/labelslexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -97,27 +80,7 @@ pub struct LabelsLexerActions { impl LabelsLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for LabelsLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for LabelsLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "LabelsLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { LabelsLexerActions, "LabelsLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/labelsparser.rs b/runtime/Rust/tests/gen/labelsparser.rs index 7bd3bb3b56..14941ef64a 100644 --- a/runtime/Rust/tests/gen/labelsparser.rs +++ b/runtime/Rust/tests/gen/labelsparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::labelslistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const Labels_T__0:i32=1; pub const Labels_T__1:i32=2; @@ -165,32 +140,7 @@ pub struct LabelsParserExt<'input, 'arena> { impl<'input, 'arena> LabelsParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for LabelsParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for LabelsParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "Labels.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena LabelsParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 1 => LabelsParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { LabelsParserExt, LabelsParserNodeKind, "Labels.g4"; sempred (LabelsParserNode<'input, 'arena, TF::Tok>, LabelsParser) { 1 => e_sempred, } } impl<'input, 'arena, Input, TF> LabelsParser<'input, 'arena, Input, TF> where @@ -227,37 +177,7 @@ pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @plain LabelsParserNodeKind::SContext, SContextExt, RULE_s } impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena LabelsParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut LabelsParserNode<'input, 'arena, Tok>, ANTLRError> @@ -269,7 +189,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, To ) } } - pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -298,50 +217,35 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(11); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - Labels_T__4 |Labels_ID |Labels_INT => { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule e*/ - recog.base.set_state(6); - let tmp = recog.e_rec(0)?; - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().q = Some(tmp); } - }} - Labels_T__0 => { - /*------- Outer Most Alt 2 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } - { - recog.base.set_state(7); - recog.base.match_token(Labels_T__0,&mut recog.err_handler)?; - /*InvokeRule blk*/ - recog.base.set_state(8); - recog.blk()?; - recog.base.set_state(9); - recog.base.match_token(Labels_T__1,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(11); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + Labels_T__4 |Labels_ID |Labels_INT => { + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(6); + let tmp = recog.e_rec(0)?; + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().q = Some(tmp); } + }} + Labels_T__0 => { + /*------- Outer Most Alt 2 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(2); } + { + recog.base.set_state(7); + recog.base.match_token(Labels_T__0,&mut recog.err_handler)?; + /*InvokeRule blk*/ + recog.base.set_state(8); + recog.blk()?; + recog.base.set_state(9); + recog.base.match_token(Labels_T__1,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- e ---------------- @@ -396,39 +300,7 @@ pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: EContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled LabelsParserNodeKind::EContext, EContextAll, EContextExt, RULE_e } impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena LabelsParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut LabelsParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -441,7 +313,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, To ) } } - pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -487,42 +358,7 @@ pub struct AddContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AddContextExt<'input, 'arena, Tok> -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: AddContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::AddContext(ctx)) - } - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LabelsParserNodeKind::EContext, EContextAll::AddContext, AddContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> where @@ -587,42 +423,7 @@ pub struct ParensContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ParensContextExt<'input, 'arena, Tok> -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: ParensContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::ParensContext(ctx)) - } - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ParensContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::ParensContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ParensContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::ParensContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LabelsParserNodeKind::EContext, EContextAll::ParensContext, ParensContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ParensContext<'input, 'arena, Tok> where @@ -693,42 +494,7 @@ pub struct MultContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for MultContextExt<'input, 'arena, Tok> -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: MultContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::MultContext(ctx)) - } - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a MultContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::MultContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut MultContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::MultContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LabelsParserNodeKind::EContext, EContextAll::MultContext, MultContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for MultContext<'input, 'arena, Tok> where @@ -794,42 +560,7 @@ pub struct DecContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for DecContextExt<'input, 'arena, Tok> -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: DecContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::DecContext(ctx)) - } - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a DecContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::DecContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut DecContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::DecContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LabelsParserNodeKind::EContext, EContextAll::DecContext, DecContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for DecContext<'input, 'arena, Tok> where @@ -898,42 +629,7 @@ pub struct AnIDContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AnIDContextExt<'input, 'arena, Tok> -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: AnIDContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::AnIDContext(ctx)) - } - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AnIDContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::AnIDContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AnIDContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::AnIDContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LabelsParserNodeKind::EContext, EContextAll::AnIDContext, AnIDContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AnIDContext<'input, 'arena, Tok> where @@ -1002,42 +698,7 @@ pub struct AnIntContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonT pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AnIntContextExt<'input, 'arena, Tok> -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: AnIntContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::AnIntContext(ctx)) - } - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AnIntContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::AnIntContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AnIntContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::AnIntContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LabelsParserNodeKind::EContext, EContextAll::AnIntContext, AnIntContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AnIntContext<'input, 'arena, Tok> where @@ -1102,42 +763,7 @@ pub struct IncContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for IncContextExt<'input, 'arena, Tok> -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: IncContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::IncContext(ctx)) - } - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a IncContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::IncContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut IncContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::IncContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LabelsParserNodeKind::EContext, EContextAll::IncContext, IncContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for IncContext<'input, 'arena, Tok> where @@ -1191,240 +817,179 @@ where } fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, EContext, RULE_e, 2, |_parentctx| EContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 2; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(23); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - Labels_INT => { - { - recog.base.with_mut_ctx(|ctx| { AnIntContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena AnIntContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(14); - let tmp = recog.base.match_token(Labels_INT,&mut recog.err_handler)?; - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().INT = Some(tmp); } - let tmp = { if let Some(it) = &recog.ctx().unwrap().as_rule_context::>().unwrap().INT { it.get_text() } else { "null" } .to_owned()}.to_owned(); - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } - }} - Labels_T__4 => { - { - recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(16); - recog.base.match_token(Labels_T__4,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(17); - let tmp = recog.e_rec(0)?; - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().x = Some(tmp); } - recog.base.set_state(18); - recog.base.match_token(Labels_T__5,&mut recog.err_handler)?; - let tmp = { recog.ctx().unwrap().as_rule_context::>().unwrap().x.as_ref().unwrap().get_v()}.to_owned(); - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } - }} - Labels_ID => { - { - recog.base.with_mut_ctx(|ctx| { AnIDContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena AnIDContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(21); - let tmp = recog.base.match_token(Labels_ID,&mut recog.err_handler)?; - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().ID = Some(tmp); } - let tmp = { if let Some(it) = &recog.ctx().unwrap().as_rule_context::>().unwrap().ID { it.get_text() } else { "null" } .to_owned()}.to_owned(); - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(43); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(41); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - MultContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena MultContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.with_mut_ctx(|ctx| { - ctx.as_rule_context_mut::>().unwrap().a = Some(_prevctx.as_rule_context().unwrap()); - }); - - recog.base.set_state(25); - if !({recog.precpred(None, 7)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 7)".to_owned()), None))?; - } - recog.base.set_state(26); - let tmp = recog.base.match_token(Labels_T__2,&mut recog.err_handler)?; - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().op = Some(tmp); } - /*InvokeRule e*/ - recog.base.set_state(27); - let tmp = recog.e_rec(8)?; - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().b = Some(tmp); } - let tmp = { "* ".to_owned() + recog.ctx().unwrap().as_rule_context::>().unwrap().a.as_ref().unwrap().get_v() + " " + recog.ctx().unwrap().as_rule_context::>().unwrap().b.as_ref().unwrap().get_v()}.to_owned(); - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(23); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + Labels_INT => { + { + recog.base.with_mut_ctx(|ctx| { AnIntContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena AnIntContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(14); + let tmp = recog.base.match_token(Labels_INT,&mut recog.err_handler)?; + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().INT = Some(tmp); } + let tmp = { if let Some(it) = &recog.ctx().unwrap().as_rule_context::>().unwrap().INT { it.get_text() } else { "null" } .to_owned()}.to_owned(); + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } + }} + Labels_T__4 => { + { + recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(16); + recog.base.match_token(Labels_T__4,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(17); + let tmp = recog.e_rec(0)?; + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().x = Some(tmp); } + recog.base.set_state(18); + recog.base.match_token(Labels_T__5,&mut recog.err_handler)?; + let tmp = { recog.ctx().unwrap().as_rule_context::>().unwrap().x.as_ref().unwrap().get_v()}.to_owned(); + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } + }} + Labels_ID => { + { + recog.base.with_mut_ctx(|ctx| { AnIDContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena AnIDContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(21); + let tmp = recog.base.match_token(Labels_ID,&mut recog.err_handler)?; + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().ID = Some(tmp); } + let tmp = { if let Some(it) = &recog.ctx().unwrap().as_rule_context::>().unwrap().ID { it.get_text() } else { "null" } .to_owned()}.to_owned(); + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(43); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(41); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(2,&mut recog.base)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + MultContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena MultContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.with_mut_ctx(|ctx| { + ctx.as_rule_context_mut::>().unwrap().a = Some(_prevctx.as_rule_context().unwrap()); + }); + + recog.base.set_state(25); + if !({recog.precpred(None, 7)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 7)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AddContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.with_mut_ctx(|ctx| { - ctx.as_rule_context_mut::>().unwrap().a = Some(_prevctx.as_rule_context().unwrap()); - }); - - recog.base.set_state(30); - if !({recog.precpred(None, 6)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; - } - recog.base.set_state(31); - recog.base.match_token(Labels_T__3,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(32); - let tmp = recog.e_rec(7)?; - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().b = Some(tmp); } - let tmp = { "+ ".to_owned() + recog.ctx().unwrap().as_rule_context::>().unwrap().a.as_ref().unwrap().get_v() + " " + recog.ctx().unwrap().as_rule_context::>().unwrap().b.as_ref().unwrap().get_v()}.to_owned(); - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } - } + recog.base.set_state(26); + let tmp = recog.base.match_token(Labels_T__2,&mut recog.err_handler)?; + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().op = Some(tmp); } + /*InvokeRule e*/ + recog.base.set_state(27); + let tmp = recog.e_rec(8)?; + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().b = Some(tmp); } + let tmp = { "* ".to_owned() + recog.ctx().unwrap().as_rule_context::>().unwrap().a.as_ref().unwrap().get_v() + " " + recog.ctx().unwrap().as_rule_context::>().unwrap().b.as_ref().unwrap().get_v()}.to_owned(); + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } } - , - 3 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - IncContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena IncContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.with_mut_ctx(|ctx| { - ctx.as_rule_context_mut::>().unwrap().x = Some(_prevctx.as_rule_context().unwrap()); - }); - - recog.base.set_state(35); - if !({recog.precpred(None, 3)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; - } - recog.base.set_state(36); - recog.base.match_token(Labels_T__6,&mut recog.err_handler)?; - let tmp = { " ++".to_owned() + recog.ctx().unwrap().as_rule_context::>().unwrap().x.as_ref().unwrap().get_v()}.to_owned(); - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } - } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AddContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.with_mut_ctx(|ctx| { + ctx.as_rule_context_mut::>().unwrap().a = Some(_prevctx.as_rule_context().unwrap()); + }); + + recog.base.set_state(30); + if !({recog.precpred(None, 6)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; } - , - 4 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - DecContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena DecContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.with_mut_ctx(|ctx| { - ctx.as_rule_context_mut::>().unwrap().x = Some(_prevctx.as_rule_context().unwrap()); - }); - - recog.base.set_state(38); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(39); - recog.base.match_token(Labels_T__7,&mut recog.err_handler)?; - let tmp = { " --".to_owned() + recog.ctx().unwrap().as_rule_context::>().unwrap().x.as_ref().unwrap().get_v()}.to_owned(); - unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } - } + recog.base.set_state(31); + recog.base.match_token(Labels_T__3,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(32); + let tmp = recog.e_rec(7)?; + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().b = Some(tmp); } + let tmp = { "+ ".to_owned() + recog.ctx().unwrap().as_rule_context::>().unwrap().a.as_ref().unwrap().get_v() + " " + recog.ctx().unwrap().as_rule_context::>().unwrap().b.as_ref().unwrap().get_v()}.to_owned(); + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } + } + } + , + 3 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + IncContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena IncContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.with_mut_ctx(|ctx| { + ctx.as_rule_context_mut::>().unwrap().x = Some(_prevctx.as_rule_context().unwrap()); + }); + + recog.base.set_state(35); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(36); + recog.base.match_token(Labels_T__6,&mut recog.err_handler)?; + let tmp = { " ++".to_owned() + recog.ctx().unwrap().as_rule_context::>().unwrap().x.as_ref().unwrap().get_v()}.to_owned(); + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } + } + } + , + 4 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + DecContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena DecContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.with_mut_ctx(|ctx| { + ctx.as_rule_context_mut::>().unwrap().x = Some(_prevctx.as_rule_context().unwrap()); + }); + + recog.base.set_state(38); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; + } + recog.base.set_state(39); + recog.base.match_token(Labels_T__7,&mut recog.err_handler)?; + let tmp = { " --".to_owned() + recog.ctx().unwrap().as_rule_context::>().unwrap().x.as_ref().unwrap().get_v()}.to_owned(); + unsafe { recog.ctx_mut().unwrap().as_rule_context_mut::>().unwrap().set_v(tmp); } } - - _ => {} } - } + + _ => {} } - recog.base.set_state(45); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(45); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(3,&mut recog.base)?; + } } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + }) } } //------------------- blk ---------------- pub type BlkContextAll<'input, 'arena, Tok = CommonToken<'input>> = BlkContext<'input, 'arena, Tok>; -pub type BlkContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, BlkContextExt<'input, 'arena, Tok>, LabelsParserNodeKind, Tok>; -#[derive(Debug)] -pub struct BlkContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for BlkContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = LabelsParserNodeKind; - fn node_tag() -> LabelsParserNodeKind { LabelsParserNodeKind::BlkContext } - fn get_rule_index(&self) -> usize { RULE_blk } - fn make_node( - arena: &'arena Arena, - ctx: BlkContext<'input, 'arena, Tok>, - ) -> *mut LabelsParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a BlkContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => BlkContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LabelsParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut BlkContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut BlkContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> BlkContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena LabelsParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut LabelsParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, BlkContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { LabelsParserNodeKind, BlkContext, BlkContextExt, RULE_blk } pub trait BlkContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1450,31 +1015,16 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn blk(&mut self,) -> Result<&'arena BlkContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(BlkContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_blk)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, BlkContext, RULE_blk, 4, |_parentctx| BlkContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena BlkContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule s*/ - recog.base.set_state(46); - recog.s()?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule s*/ + recog.base.set_state(46); + recog.s()?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/lrdfalexer.rs b/runtime/Rust/tests/gen/lrdfalexer.rs index dc1bf43b7e..43c4fd2735 100644 --- a/runtime/Rust/tests/gen/lrdfalexer.rs +++ b/runtime/Rust/tests/gen/lrdfalexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -99,27 +82,7 @@ pub struct LrDfaLexerActions { impl LrDfaLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for LrDfaLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for LrDfaLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "LrDfaLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { LrDfaLexerActions, "LrDfaLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/lrdfaparser.rs b/runtime/Rust/tests/gen/lrdfaparser.rs index 8b6cec8339..ec2463e63b 100644 --- a/runtime/Rust/tests/gen/lrdfaparser.rs +++ b/runtime/Rust/tests/gen/lrdfaparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::lrdfalistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const LrDfa_T__0:i32=1; pub const LrDfa_T__1:i32=2; @@ -165,32 +140,7 @@ pub struct LrDfaParserExt<'input, 'arena> { impl<'input, 'arena> LrDfaParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for LrDfaParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for LrDfaParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "LrDfa.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena LrDfaParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 1 => LrDfaParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { LrDfaParserExt, LrDfaParserNodeKind, "LrDfa.g4"; sempred (LrDfaParserNode<'input, 'arena, TF::Tok>, LrDfaParser) { 1 => e_sempred, } } impl<'input, 'arena, Input, TF> LrDfaParser<'input, 'arena, Input, TF> where @@ -226,53 +176,7 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, LrDfaParserNodeKind, Tok>; -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena LrDfaParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut LrDfaParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { LrDfaParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -306,33 +210,18 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule e*/ - recog.base.set_state(4); - recog.e_rec(0)?; - recog.base.set_state(5); - recog.base.match_token(LrDfa_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(4); + recog.e_rec(0)?; + recog.base.set_state(5); + recog.base.match_token(LrDfa_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- e ---------------- @@ -390,39 +279,7 @@ pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: EContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled LrDfaParserNodeKind::EContext, EContextAll, EContextExt, RULE_e } impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena LrDfaParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut LrDfaParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -432,7 +289,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, To ) } } - pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -472,42 +328,7 @@ pub struct AddContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AddContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: AddContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::AddContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::AddContext, AddContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> where @@ -568,42 +389,7 @@ pub struct NegContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NegContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: NegContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::NegContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NegContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::NegContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NegContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::NegContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::NegContext, NegContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for NegContext<'input, 'arena, Tok> where @@ -668,42 +454,7 @@ pub struct MulContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for MulContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: MulContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::MulContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a MulContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::MulContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut MulContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::MulContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::MulContext, MulContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> where @@ -768,42 +519,7 @@ pub struct TernaryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Commo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for TernaryContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: TernaryContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::TernaryContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a TernaryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::TernaryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut TernaryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::TernaryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::TernaryContext, TernaryContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for TernaryContext<'input, 'arena, Tok> where @@ -868,42 +584,7 @@ pub struct PowContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for PowContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: PowContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::PowContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PowContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::PowContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PowContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::PowContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::PowContext, PowContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for PowContext<'input, 'arena, Tok> where @@ -968,42 +649,7 @@ pub struct IndexContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonT pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for IndexContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: IndexContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::IndexContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a IndexContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::IndexContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut IndexContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::IndexContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::IndexContext, IndexContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for IndexContext<'input, 'arena, Tok> where @@ -1068,42 +714,7 @@ pub struct IdContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToke pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for IdContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: IdContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::IdContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a IdContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::IdContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut IdContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::IdContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::IdContext, IdContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for IdContext<'input, 'arena, Tok> where @@ -1164,42 +775,7 @@ pub struct FactContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for FactContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: FactContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::FactContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a FactContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::FactContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut FactContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::FactContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::FactContext, FactContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for FactContext<'input, 'arena, Tok> where @@ -1264,42 +840,7 @@ pub struct IntContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for IntContextExt<'input, 'arena, Tok> -{ - type NodeKind = LrDfaParserNodeKind; - fn node_tag() -> LrDfaParserNodeKind { LrDfaParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: IntContext<'input, 'arena, Tok>, - ) -> *mut LrDfaParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::IntContext(ctx)) - } - fn cast_from<'a>( - node: &'a LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a IntContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::IntContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut LrDfaParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut IntContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::IntContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt LrDfaParserNodeKind::EContext, EContextAll::IntContext, IntContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for IntContext<'input, 'arena, Tok> where @@ -1350,221 +891,206 @@ where } fn e_rec(&mut self, _p: i32) -> Result<&'arena EContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, EContext, RULE_e, 2, |_parentctx| EContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 2; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(12); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - LrDfa_T__3 => { - { - recog.base.with_mut_ctx(|ctx| { NegContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena NegContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(8); - recog.base.match_token(LrDfa_T__3,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(9); - recog.e_rec(7)?; - }} - LrDfa_ID => { - { - recog.base.with_mut_ctx(|ctx| { IdContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena IdContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(10); - recog.base.match_token(LrDfa_ID,&mut recog.err_handler)?; - }} - LrDfa_INT => { - { - recog.base.with_mut_ctx(|ctx| { IntContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena IntContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(11); - recog.base.match_token(LrDfa_INT,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(38); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } }; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(36); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(1)?; _sdp } { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - PowContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena PowContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(14); - if !({recog.precpred(None, 6)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; - } - recog.base.set_state(15); - recog.base.match_token(LrDfa_T__4,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(16); - recog.e_rec(6)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(12); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + LrDfa_T__3 => { + { + recog.base.with_mut_ctx(|ctx| { NegContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NegContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(8); + recog.base.match_token(LrDfa_T__3,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(9); + recog.e_rec(7)?; + }} + LrDfa_ID => { + { + recog.base.with_mut_ctx(|ctx| { IdContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena IdContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(10); + recog.base.match_token(LrDfa_ID,&mut recog.err_handler)?; + }} + LrDfa_INT => { + { + recog.base.with_mut_ctx(|ctx| { IntContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena IntContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(11); + recog.base.match_token(LrDfa_INT,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(38); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(36); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(1)?; _sdp } { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + PowContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena PowContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(14); + if !({recog.precpred(None, 6)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 6)".to_owned()), None))?; + } + recog.base.set_state(15); + recog.base.match_token(LrDfa_T__4,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(16); + recog.e_rec(6)?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - MulContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(17); - if !({recog.precpred(None, 5)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 5)".to_owned()), None))?; - } - recog.base.set_state(18); - _la = recog.base.input.la(1); - if { !(_la==LrDfa_T__5 || _la==LrDfa_T__6) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(19); - recog.e_rec(6)?; - } + } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + MulContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(17); + if !({recog.precpred(None, 5)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 5)".to_owned()), None))?; + } + recog.base.set_state(18); + _la = recog.base.input.la(1); + if { !(_la==LrDfa_T__5 || _la==LrDfa_T__6) } { + recog.err_handler.recover_inline(&mut recog.base)?; } - , - 3 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AddContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(20); - if !({recog.precpred(None, 4)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; - } - recog.base.set_state(21); - _la = recog.base.input.la(1); - if { !(_la==LrDfa_T__3 || _la==LrDfa_T__7) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(22); - recog.e_rec(5)?; - } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; } - , - 4 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - TernaryContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena TernaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(23); - if !({recog.precpred(None, 3)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; - } - recog.base.set_state(24); - recog.base.match_token(LrDfa_T__8,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(25); - recog.e_rec(0)?; - recog.base.set_state(26); - recog.base.match_token(LrDfa_T__9,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(27); - recog.e_rec(3)?; - } + /*InvokeRule e*/ + recog.base.set_state(19); + recog.e_rec(6)?; } - , - 5 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - IndexContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena IndexContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(29); - if !({recog.precpred(None, 9)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 9)".to_owned()), None))?; - } - recog.base.set_state(30); - recog.base.match_token(LrDfa_T__0,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(31); - recog.e_rec(0)?; - recog.base.set_state(32); - recog.base.match_token(LrDfa_T__1,&mut recog.err_handler)?; - } + } + , + 3 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AddContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(20); + if !({recog.precpred(None, 4)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 4)".to_owned()), None))?; } - , - 6 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - FactContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena FactContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(34); - if !({recog.precpred(None, 8)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 8)".to_owned()), None))?; - } - recog.base.set_state(35); - recog.base.match_token(LrDfa_T__2,&mut recog.err_handler)?; - } + recog.base.set_state(21); + _la = recog.base.input.la(1); + if { !(_la==LrDfa_T__3 || _la==LrDfa_T__7) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(22); + recog.e_rec(5)?; + } + } + , + 4 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + TernaryContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena TernaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(23); + if !({recog.precpred(None, 3)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 3)".to_owned()), None))?; + } + recog.base.set_state(24); + recog.base.match_token(LrDfa_T__8,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(25); + recog.e_rec(0)?; + recog.base.set_state(26); + recog.base.match_token(LrDfa_T__9,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(27); + recog.e_rec(3)?; } - - _ => {} } - } + , + 5 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + IndexContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena IndexContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(29); + if !({recog.precpred(None, 9)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 9)".to_owned()), None))?; + } + recog.base.set_state(30); + recog.base.match_token(LrDfa_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(31); + recog.e_rec(0)?; + recog.base.set_state(32); + recog.base.match_token(LrDfa_T__1,&mut recog.err_handler)?; + } + } + , + 6 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + FactContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena FactContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(34); + if !({recog.precpred(None, 8)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 8)".to_owned()), None))?; + } + recog.base.set_state(35); + recog.base.match_token(LrDfa_T__2,&mut recog.err_handler)?; + } + } + + _ => {} } - recog.base.set_state(40); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } }; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(40); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(2)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(2,&mut recog.base)? } else { _sdp } }; + } } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + }) } } diff --git a/runtime/Rust/tests/gen/parenexprlexer.rs b/runtime/Rust/tests/gen/parenexprlexer.rs index 1bc467cf59..12812e1871 100644 --- a/runtime/Rust/tests/gen/parenexprlexer.rs +++ b/runtime/Rust/tests/gen/parenexprlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -97,27 +80,7 @@ pub struct ParenExprLexerActions { impl ParenExprLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for ParenExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for ParenExprLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "ParenExprLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { ParenExprLexerActions, "ParenExprLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/parenexprparser.rs b/runtime/Rust/tests/gen/parenexprparser.rs index 5c84c016ec..d0a020379a 100644 --- a/runtime/Rust/tests/gen/parenexprparser.rs +++ b/runtime/Rust/tests/gen/parenexprparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::parenexprlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const ParenExpr_T__0:i32=1; pub const ParenExpr_T__1:i32=2; @@ -165,32 +140,7 @@ pub struct ParenExprParserExt<'input, 'arena> { impl<'input, 'arena> ParenExprParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ParenExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ParenExprParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "ParenExpr.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena ParenExprParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 1 => ParenExprParser::<'input, 'arena, Input, TF>::e_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { ParenExprParserExt, ParenExprParserNodeKind, "ParenExpr.g4"; sempred (ParenExprParserNode<'input, 'arena, TF::Tok>, ParenExprParser) { 1 => e_sempred, } } impl<'input, 'arena, Input, TF> ParenExprParser<'input, 'arena, Input, TF> where @@ -214,53 +164,7 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, ParenExprParserNodeKind, Tok>; -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { ParenExprParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -294,33 +198,18 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule e*/ - recog.base.set_state(6); - recog.e_rec(0)?; - recog.base.set_state(7); - recog.base.match_token(ParenExpr_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule e*/ + recog.base.set_state(6); + recog.e_rec(0)?; + recog.base.set_state(7); + recog.base.match_token(ParenExpr_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- e ---------------- @@ -376,39 +265,7 @@ pub struct EContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for EContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: EContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => EContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut EContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut EContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled ParenExprParserNodeKind::EContext, EContextAll, EContextExt, RULE_e } impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -418,7 +275,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> EContextExt<'input, 'arena, To ) } } - pub trait EContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -458,42 +314,7 @@ pub struct AddContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AddContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: AddContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::AddContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::AddContext, AddContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> where @@ -558,42 +379,7 @@ pub struct ColContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ColContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: ColContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::ColContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ColContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::ColContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ColContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::ColContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::ColContext, ColContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ColContext<'input, 'arena, Tok> where @@ -654,42 +440,7 @@ pub struct ParensContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for ParensContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: ParensContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::ParensContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ParensContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::ParensContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ParensContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::ParensContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::ParensContext, ParensContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for ParensContext<'input, 'arena, Tok> where @@ -750,42 +501,7 @@ pub struct SubqueryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Comm pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for SubqueryContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: SubqueryContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::SubqueryContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SubqueryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::SubqueryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SubqueryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::SubqueryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::SubqueryContext, SubqueryContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for SubqueryContext<'input, 'arena, Tok> where @@ -850,42 +566,7 @@ pub struct RowConstructorContextExt<'input: 'arena, 'arena, Tok: Token + 'input pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for RowConstructorContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: RowConstructorContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::RowConstructorContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a RowConstructorContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::RowConstructorContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut RowConstructorContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::RowConstructorContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::RowConstructorContext, RowConstructorContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for RowConstructorContext<'input, 'arena, Tok> where @@ -950,42 +631,7 @@ pub struct MulContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for MulContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: MulContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::MulContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a MulContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::MulContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut MulContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::MulContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::MulContext, MulContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for MulContext<'input, 'arena, Tok> where @@ -1050,42 +696,7 @@ pub struct NumContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NumContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: NumContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::NumContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NumContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::NumContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NumContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::NumContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::NumContext, NumContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for NumContext<'input, 'arena, Tok> where @@ -1146,42 +757,7 @@ pub struct UnaryContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonT pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for UnaryContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::EContext } - fn get_rule_index(&self) -> usize { RULE_e } - fn make_node( - arena: &'arena Arena, - ctx: UnaryContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(EContextAll::UnaryContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a UnaryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => EContextAll<'input, 'arena, Tok>) { - EContextAll::UnaryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut UnaryContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut EContextAll<'input, 'arena, Tok>) { - EContextAll::UnaryContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::EContext, EContextAll::UnaryContext, UnaryContextExt, RULE_e } impl<'input, 'arena, Tok> EContextAttrs<'input, 'arena, Tok> for UnaryContext<'input, 'arena, Tok> where @@ -1235,248 +811,233 @@ where if let Some(_node) = self.base.resume_take(RULE_e)? { return Ok(_node.as_rule_context().unwrap()); } - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(EContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_e, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, EContext, RULE_e, 2, |_parentctx| EContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena EContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 2; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + recog.err_handler.sync(&mut recog.base)?; + match { let _m = recog.base.dfa_predict_mask(1)?; + match _m { + 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), + x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [ParenExpr_T__0 | ParenExpr_T__3 | ParenExpr_ID | ParenExpr_INT].contains(&recog.input.la(2)) => { + recog.base.set_state(13); + let _neutral_state = recog.base.begin_neutral_parse(1); + match recog.e() { + Err(e) if !e.is_recoverable() => { + recog.base.end_neutral_parse(&_neutral_state); + return Err(e) + }, + Err(_) => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) + }, + Ok(_node) => { + if recog.base.syntax_error_count() != _neutral_state.2 { + recog.base.end_neutral_parse(&_neutral_state); + // errorful neutral parse: throw its result away and + // defer (muted, so no spurious reports escaped) + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) + } + else { + // the tail token decides on the post-prefix stream. + // An explicit arm (or the static default) rewinds into + // resume mode; anything else rewinds and defers to the + // adaptive engine from the decision start - no resume, + // the chosen body re-parses everything + let _tailbit = { let _t = recog.input.la(1); match _t { + ParenExpr_T__1 if !false || !recog.base.follow_contains(_t) => Some(0x4), + ParenExpr_T__2 if !false || !recog.base.follow_contains(_t) => Some(0x8), + _ => None, + } }; + match _tailbit { + Some(bit) => { + recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e); + recog.base.end_neutral_parse(&_neutral_state); + bit + } + None => { + recog.base.end_neutral_parse(&_neutral_state); + 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) + } + } + } + }, + } + }, + x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), + x if (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), + m => m, + } } { + x if x == 0x1 =>{ { - recog.base.set_state(32); - recog.err_handler.sync(&mut recog.base)?; - match { let _m = recog.base.dfa_predict_mask(1)?; - match _m { - 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), - x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 && !recog.base.resume_active() && [ParenExpr_T__0 | ParenExpr_T__3 | ParenExpr_ID | ParenExpr_INT].contains(&recog.input.la(2)) => { - recog.base.set_state(13); - let _neutral_state = recog.base.begin_neutral_parse(1); - match recog.e() { - Err(e) if !e.is_recoverable() => { - recog.base.end_neutral_parse(&_neutral_state); - return Err(e) - }, - Err(_) => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) - }, - Ok(_node) => { - if recog.base.syntax_error_count() != _neutral_state.2 { - recog.base.end_neutral_parse(&_neutral_state); - // errorful neutral parse: throw its result away and - // defer (muted, so no spurious reports escaped) - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) - } - else { - // the tail token decides on the post-prefix stream. - // An explicit arm (or the static default) rewinds into - // resume mode; anything else rewinds and defers to the - // adaptive engine from the decision start - no resume, - // the chosen body re-parses everything - let _tailbit = { let _t = recog.input.la(1); match _t { - ParenExpr_T__1 if !false || !recog.base.follow_contains(_t) => Some(0x4), - ParenExpr_T__2 if !false || !recog.base.follow_contains(_t) => Some(0x8), - _ => None, - } }; - match _tailbit { - Some(bit) => { - recog.base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_e); - recog.base.end_neutral_parse(&_neutral_state); - bit - } - None => { - recog.base.end_neutral_parse(&_neutral_state); - 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32) - } - } - } - }, - } - }, - x if x != 0 && (x & !0x1c) == 0 && (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), - x if (x & (x-1)) != 0 => 1u64.wrapping_shl((recog.get_interpreter().adaptive_predict(1,&mut recog.base)? - 1) as u32), - m => m, - } } { - x if x == 0x1 =>{ - { - recog.base.with_mut_ctx(|ctx| { NumContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena NumContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.with_mut_ctx(|ctx| { NumContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NumContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(10); - recog.base.match_token(ParenExpr_INT,&mut recog.err_handler)?; - } - }, - x if x == 0x2 =>{ + recog.base.set_state(10); + recog.base.match_token(ParenExpr_INT,&mut recog.err_handler)?; + } + }, + x if x == 0x2 =>{ + { + recog.base.with_mut_ctx(|ctx| { ColContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ColContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(11); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + } + }, + x if x == 0x4 =>{ + { + recog.base.with_mut_ctx(|ctx| { RowConstructorContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena RowConstructorContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(12); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(13); + recog.e_rec(0)?; + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + loop { { - recog.base.with_mut_ctx(|ctx| { ColContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena ColContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(11); - recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; - } - }, - x if x == 0x4 =>{ { - recog.base.with_mut_ctx(|ctx| { RowConstructorContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena RowConstructorContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(12); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + recog.base.set_state(14); + recog.base.match_token(ParenExpr_T__1,&mut recog.err_handler)?; /*InvokeRule e*/ - recog.base.set_state(13); + recog.base.set_state(15); recog.e_rec(0)?; - recog.base.set_state(16); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - loop { - { - { - recog.base.set_state(14); - recog.base.match_token(ParenExpr_T__1,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(15); - recog.e_rec(0)?; - } - } - recog.base.set_state(18); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if !(_la==ParenExpr_T__1) {break} } - recog.base.set_state(20); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - } - }, - x if x == 0x8 =>{ - { - recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(22); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(23); - recog.e_rec(0)?; - recog.base.set_state(24); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - } - }, - x if x == 0x10 =>{ - { - recog.base.with_mut_ctx(|ctx| { SubqueryContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena SubqueryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(26); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule q*/ - recog.base.set_state(27); - recog.q()?; - recog.base.set_state(28); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - } - }, - x if x == 0x20 =>{ - { - recog.base.with_mut_ctx(|ctx| { UnaryContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena UnaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - recog.base.set_state(30); - recog.base.match_token(ParenExpr_T__3,&mut recog.err_handler)?; - /*InvokeRule e*/ - recog.base.set_state(31); - recog.e_rec(3)?; } + recog.base.set_state(18); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if !(_la==ParenExpr_T__1) {break} } - _ => {} + recog.base.set_state(20); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(42); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(40); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(2)?; _sdp } { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - MulContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(34); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(35); - _la = recog.base.input.la(1); - if { !(_la==ParenExpr_T__4 || _la==ParenExpr_T__5) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(36); - recog.e_rec(3)?; - } + }, + x if x == 0x8 =>{ + { + recog.base.with_mut_ctx(|ctx| { ParensContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena ParensContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(22); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(23); + recog.e_rec(0)?; + recog.base.set_state(24); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + }, + x if x == 0x10 =>{ + { + recog.base.with_mut_ctx(|ctx| { SubqueryContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena SubqueryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(26); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule q*/ + recog.base.set_state(27); + recog.q()?; + recog.base.set_state(28); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + } + }, + x if x == 0x20 =>{ + { + recog.base.with_mut_ctx(|ctx| { UnaryContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena UnaryContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + recog.base.set_state(30); + recog.base.match_token(ParenExpr_T__3,&mut recog.err_handler)?; + /*InvokeRule e*/ + recog.base.set_state(31); + recog.e_rec(3)?; + } + } + _ => {} + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(42); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(40); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(2)?; _sdp } { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + MulContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena MulContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(34); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AddContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(37); - if !({recog.precpred(None, 1)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; - } - recog.base.set_state(38); - _la = recog.base.input.la(1); - if { !(_la==ParenExpr_T__3 || _la==ParenExpr_T__6) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule e*/ - recog.base.set_state(39); - recog.e_rec(2)?; - } + recog.base.set_state(35); + _la = recog.base.input.la(1); + if { !(_la==ParenExpr_T__4 || _la==ParenExpr_T__5) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(36); + recog.e_rec(3)?; } - - _ => {} } - } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = EContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AddContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_e)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(37); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(38); + _la = recog.base.input.la(1); + if { !(_la==ParenExpr_T__3 || _la==ParenExpr_T__6) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule e*/ + recog.base.set_state(39); + recog.e_rec(2)?; + } + } + + _ => {} } - recog.base.set_state(44); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; + } } - } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(44); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; if _sdp == INVALID_ALT { recog.get_interpreter().adaptive_predict(3,&mut recog.base)? } else { _sdp } }; } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + } + }) } } //------------------- q ---------------- @@ -1522,39 +1083,7 @@ pub struct QContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for QContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: QContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(QContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a QContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => QContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut QContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut QContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled ParenExprParserNodeKind::QContext, QContextAll, QContextExt, RULE_q } impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena ParenExprParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ParenExprParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -1564,7 +1093,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> QContextExt<'input, 'arena, To ) } } - pub trait QContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -1604,42 +1132,7 @@ pub struct SelectContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for SelectContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: SelectContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(QContextAll::SelectContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SelectContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { - QContextAll::SelectContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SelectContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { - QContextAll::SelectContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::QContext, QContextAll::SelectContext, SelectContextExt, RULE_q } impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for SelectContext<'input, 'arena, Tok> where @@ -1700,42 +1193,7 @@ pub struct NestedContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NestedContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: NestedContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(QContextAll::NestedContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NestedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { - QContextAll::NestedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NestedContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { - QContextAll::NestedContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::QContext, QContextAll::NestedContext, NestedContextExt, RULE_q } impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for NestedContext<'input, 'arena, Tok> where @@ -1800,42 +1258,7 @@ pub struct TableContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonT pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for TableContextExt<'input, 'arena, Tok> -{ - type NodeKind = ParenExprParserNodeKind; - fn node_tag() -> ParenExprParserNodeKind { ParenExprParserNodeKind::QContext } - fn get_rule_index(&self) -> usize { RULE_q } - fn make_node( - arena: &'arena Arena, - ctx: TableContext<'input, 'arena, Tok>, - ) -> *mut ParenExprParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(QContextAll::TableContext(ctx)) - } - fn cast_from<'a>( - node: &'a ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a TableContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => QContextAll<'input, 'arena, Tok>) { - QContextAll::TableContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ParenExprParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut TableContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut QContextAll<'input, 'arena, Tok>) { - QContextAll::TableContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt ParenExprParserNodeKind::QContext, QContextAll::TableContext, TableContextExt, RULE_q } impl<'input, 'arena, Tok> QContextAttrs<'input, 'arena, Tok> for TableContext<'input, 'arena, Tok> where @@ -1881,69 +1304,54 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn q(&mut self,) -> Result<&'arena QContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(QContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_q)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, QContext, RULE_q, 4, |_parentctx| QContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena QContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(52); - recog.err_handler.sync(&mut recog.base)?; - match recog.base.input.la(1) { - ParenExpr_T__7 => { - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - SelectContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena SelectContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(45); - recog.base.match_token(ParenExpr_T__7,&mut recog.err_handler)?; - recog.base.set_state(46); - recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; - }} - ParenExpr_ID => { - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - TableContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena TableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(47); - recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; - }} - ParenExpr_T__0 => { - /*------- Outer Most Alt 3 -------*/ - recog.base.with_mut_ctx(|ctx| { - NestedContextExt::copy_from(ctx); - ctx.set_alt_number(3); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena NestedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(48); - recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; - /*InvokeRule q*/ - recog.base.set_state(49); - recog.q()?; - recog.base.set_state(50); - recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; - }} - _ => Err(ANTLRError::no_alt(&mut recog.base))? - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(52); + recog.err_handler.sync(&mut recog.base)?; + match recog.base.input.la(1) { + ParenExpr_T__7 => { + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + SelectContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena SelectContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(45); + recog.base.match_token(ParenExpr_T__7,&mut recog.err_handler)?; + recog.base.set_state(46); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + }} + ParenExpr_ID => { + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + TableContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena TableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(47); + recog.base.match_token(ParenExpr_ID,&mut recog.err_handler)?; + }} + ParenExpr_T__0 => { + /*------- Outer Most Alt 3 -------*/ + recog.base.with_mut_ctx(|ctx| { + NestedContextExt::copy_from(ctx); + ctx.set_alt_number(3); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena NestedContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(48); + recog.base.match_token(ParenExpr_T__0,&mut recog.err_handler)?; + /*InvokeRule q*/ + recog.base.set_state(49); + recog.q()?; + recog.base.set_state(50); + recog.base.match_token(ParenExpr_T__2,&mut recog.err_handler)?; + }} + _ => Err(ANTLRError::no_alt(&mut recog.base))? } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/referencetoatnlexer.rs b/runtime/Rust/tests/gen/referencetoatnlexer.rs index 79bfaf4268..8a1e6302c9 100644 --- a/runtime/Rust/tests/gen/referencetoatnlexer.rs +++ b/runtime/Rust/tests/gen/referencetoatnlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const ID:i32=1; @@ -85,27 +68,7 @@ pub struct ReferenceToATNLexerActions { impl ReferenceToATNLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for ReferenceToATNLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for ReferenceToATNLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "ReferenceToATNLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { ReferenceToATNLexerActions, "ReferenceToATNLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/referencetoatnparser.rs b/runtime/Rust/tests/gen/referencetoatnparser.rs index 6390ba8d73..539bc21cda 100644 --- a/runtime/Rust/tests/gen/referencetoatnparser.rs +++ b/runtime/Rust/tests/gen/referencetoatnparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::referencetoatnlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const ReferenceToATN_ID:i32=1; pub const ReferenceToATN_ATN:i32=2; @@ -150,74 +125,12 @@ pub struct ReferenceToATNParserExt<'input, 'arena> { impl<'input, 'arena> ReferenceToATNParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ReferenceToATNParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_parser_recog! { ReferenceToATNParserExt, ReferenceToATNParserNodeKind, "ReferenceToATN.g4" } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for ReferenceToATNParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "ReferenceToATN.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } -} //------------------- a ---------------- pub type AContextAll<'input, 'arena, Tok = CommonToken<'input>> = AContext<'input, 'arena, Tok>; -pub type AContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AContextExt<'input, 'arena, Tok>, ReferenceToATNParserNodeKind, Tok>; -#[derive(Debug)] -pub struct AContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = ReferenceToATNParserNodeKind; - fn node_tag() -> ReferenceToATNParserNodeKind { ReferenceToATNParserNodeKind::AContext } - fn get_rule_index(&self) -> usize { RULE_a } - fn make_node( - arena: &'arena Arena, - ctx: AContext<'input, 'arena, Tok>, - ) -> *mut ReferenceToATNParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a ReferenceToATNParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut ReferenceToATNParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> AContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena ReferenceToATNParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut ReferenceToATNParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, AContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { ReferenceToATNParserNodeKind, AContext, AContextExt, RULE_a } pub trait AContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -267,65 +180,50 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn a(&mut self,) -> Result<&'arena AContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(AContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_a)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, AContext, RULE_a, 0, |_parentctx| AContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena AContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(5); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(0,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - { - { - recog.base.set_state(2); - _la = recog.base.input.la(1); - if { !(_la==ReferenceToATN_ID || _la==ReferenceToATN_ATN) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - } - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(5); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(0,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + { + { + recog.base.set_state(2); + _la = recog.base.input.la(1); + if { !(_la==ReferenceToATN_ID || _la==ReferenceToATN_ATN) } { + recog.err_handler.recover_inline(&mut recog.base)?; } - recog.base.set_state(7); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(0,&mut recog.base)?; + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + } + } } - recog.base.set_state(9); + recog.base.set_state(7); recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - if _la==ReferenceToATN_ATN { - { - recog.base.set_state(8); - recog.base.match_token(ReferenceToATN_ATN,&mut recog.err_handler)?; - } + _alt = recog.get_interpreter().adaptive_predict(0,&mut recog.base)?; + } + recog.base.set_state(9); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + if _la==ReferenceToATN_ATN { + { + recog.base.set_state(8); + recog.base.match_token(ReferenceToATN_ATN,&mut recog.err_handler)?; } + } - println!("{}",{let temp = recog.base.input.lt(-1).map(|it|it.get_token_index()).unwrap_or(-1); recog.input.get_text_from_interval(recog.ctx().unwrap().start().get_token_index(), temp)}); - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + println!("{}",{let temp = recog.base.input.lt(-1).map(|it|it.get_token_index()).unwrap_or(-1); recog.input.get_text_from_interval(recog.ctx().unwrap().start().get_token_index(), temp)}); } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/simplelrlexer.rs b/runtime/Rust/tests/gen/simplelrlexer.rs index 3a3a3b0c65..ccc116971e 100644 --- a/runtime/Rust/tests/gen/simplelrlexer.rs +++ b/runtime/Rust/tests/gen/simplelrlexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const ID:i32=1; @@ -84,27 +67,7 @@ pub struct SimpleLRLexerActions { impl SimpleLRLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for SimpleLRLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for SimpleLRLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "SimpleLRLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { SimpleLRLexerActions, "SimpleLRLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/simplelrparser.rs b/runtime/Rust/tests/gen/simplelrparser.rs index 93a07a54df..7ebcf0b2df 100644 --- a/runtime/Rust/tests/gen/simplelrparser.rs +++ b/runtime/Rust/tests/gen/simplelrparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::simplelrlistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const SimpleLR_ID:i32=1; pub const SimpleLR_WS:i32=2; @@ -151,32 +126,7 @@ pub struct SimpleLRParserExt<'input, 'arena> { impl<'input, 'arena> SimpleLRParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for SimpleLRParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for SimpleLRParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "SimpleLR.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena SimpleLRParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 1 => SimpleLRParser::<'input, 'arena, Input, TF>::a_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { SimpleLRParserExt, SimpleLRParserNodeKind, "SimpleLR.g4"; sempred (SimpleLRParserNode<'input, 'arena, TF::Tok>, SimpleLRParser) { 1 => a_sempred, } } impl<'input, 'arena, Input, TF> SimpleLRParser<'input, 'arena, Input, TF> where @@ -197,53 +147,7 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, SimpleLRParserNodeKind, Tok>; -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = SimpleLRParserNodeKind; - fn node_tag() -> SimpleLRParserNodeKind { SimpleLRParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut SimpleLRParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a SimpleLRParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut SimpleLRParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena SimpleLRParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut SimpleLRParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { SimpleLRParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -269,85 +173,24 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule a*/ - recog.base.set_state(4); - recog.a_rec(0)?; - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); });println!("test"); - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule a*/ + recog.base.set_state(4); + recog.a_rec(0)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); });println!("test"); + }) } } //------------------- a ---------------- pub type AContextAll<'input, 'arena, Tok = CommonToken<'input>> = AContext<'input, 'arena, Tok>; -pub type AContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, AContextExt<'input, 'arena, Tok>, SimpleLRParserNodeKind, Tok>; -#[derive(Debug)] -pub struct AContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for AContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = SimpleLRParserNodeKind; - fn node_tag() -> SimpleLRParserNodeKind { SimpleLRParserNodeKind::AContext } - fn get_rule_index(&self) -> usize { RULE_a } - fn make_node( - arena: &'arena Arena, - ctx: AContext<'input, 'arena, Tok>, - ) -> *mut SimpleLRParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a SimpleLRParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => AContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut SimpleLRParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut AContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> AContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena SimpleLRParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut SimpleLRParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, AContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { SimpleLRParserNodeKind, AContext, AContextExt, RULE_a } pub trait AContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -386,61 +229,46 @@ where } fn a_rec(&mut self, _p: i32) -> Result<&'arena AContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(AContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_a, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, AContext, RULE_a, 2, |_parentctx| AContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena AContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 2; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - { - recog.base.set_state(7); - recog.base.match_token(SimpleLR_ID,&mut recog.err_handler)?; - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(13); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(0,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - { - /*recRuleAltStartAction*/ - let tmp = AContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_a)?; + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + { + recog.base.set_state(7); + recog.base.match_token(SimpleLR_ID,&mut recog.err_handler)?; + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(13); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(0,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + { + /*recRuleAltStartAction*/ + let tmp = AContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + let _prevctx = recog.push_new_recursion_context(tmp.into(), _startState, RULE_a)?; - recog.base.set_state(9); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(10); - recog.base.match_token(SimpleLR_ID,&mut recog.err_handler)?; - } - } + recog.base.set_state(9); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; } - recog.base.set_state(15); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(0,&mut recog.base)?; - } + recog.base.set_state(10); + recog.base.match_token(SimpleLR_ID,&mut recog.err_handler)?; + } + } } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(15); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(0,&mut recog.base)?; + } } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + }) } } diff --git a/runtime/Rust/tests/gen/staticdfalexer.rs b/runtime/Rust/tests/gen/staticdfalexer.rs index 1392ae5796..457034dcfc 100644 --- a/runtime/Rust/tests/gen/staticdfalexer.rs +++ b/runtime/Rust/tests/gen/staticdfalexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const T__0:i32=1; @@ -101,27 +84,7 @@ pub struct StaticDFALexerActions { impl StaticDFALexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for StaticDFALexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for StaticDFALexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "StaticDFALexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { StaticDFALexerActions, "StaticDFALexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/staticdfaparser.rs b/runtime/Rust/tests/gen/staticdfaparser.rs index f3808431dc..b0551bb675 100644 --- a/runtime/Rust/tests/gen/staticdfaparser.rs +++ b/runtime/Rust/tests/gen/staticdfaparser.rs @@ -6,34 +6,9 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::staticdfalistener::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const StaticDFA_T__0:i32=1; pub const StaticDFA_T__1:i32=2; @@ -177,24 +152,8 @@ pub struct StaticDFAParserExt<'input, 'arena> { impl<'input, 'arena> StaticDFAParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for StaticDFAParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_parser_recog! { StaticDFAParserExt, StaticDFAParserNodeKind, "StaticDFA.g4" } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for StaticDFAParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "StaticDFA.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } -} //------------------- stat ---------------- #[derive(Debug)] #[repr(C, u16)] @@ -238,39 +197,7 @@ pub struct StatContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for StatContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StatContext } - fn get_rule_index(&self) -> usize { RULE_stat } - fn make_node( - arena: &'arena Arena, - ctx: StatContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StatContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a StatContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => StatContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut StatContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut StatContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled StaticDFAParserNodeKind::StatContext, StatContextAll, StatContextExt, RULE_stat } impl<'input: 'arena, 'arena, Tok: Token + 'input> StatContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -280,7 +207,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> StatContextExt<'input, 'arena, ) } } - pub trait StatContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -320,42 +246,7 @@ pub struct CreateTableContextExt<'input: 'arena, 'arena, Tok: Token + 'input = C pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CreateTableContextExt<'input, 'arena, Tok> -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StatContext } - fn get_rule_index(&self) -> usize { RULE_stat } - fn make_node( - arena: &'arena Arena, - ctx: CreateTableContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StatContextAll::CreateTableContext(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a CreateTableContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => StatContextAll<'input, 'arena, Tok>) { - StatContextAll::CreateTableContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut CreateTableContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut StatContextAll<'input, 'arena, Tok>) { - StatContextAll::CreateTableContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt StaticDFAParserNodeKind::StatContext, StatContextAll::CreateTableContext, CreateTableContextExt, RULE_stat } impl<'input, 'arena, Tok> StatContextAttrs<'input, 'arena, Tok> for CreateTableContext<'input, 'arena, Tok> where @@ -420,42 +311,7 @@ pub struct CreateViewContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Co pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CreateViewContextExt<'input, 'arena, Tok> -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StatContext } - fn get_rule_index(&self) -> usize { RULE_stat } - fn make_node( - arena: &'arena Arena, - ctx: CreateViewContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StatContextAll::CreateViewContext(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a CreateViewContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => StatContextAll<'input, 'arena, Tok>) { - StatContextAll::CreateViewContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut CreateViewContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut StatContextAll<'input, 'arena, Tok>) { - StatContextAll::CreateViewContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt StaticDFAParserNodeKind::StatContext, StatContextAll::CreateViewContext, CreateViewContextExt, RULE_stat } impl<'input, 'arena, Tok> StatContextAttrs<'input, 'arena, Tok> for CreateViewContext<'input, 'arena, Tok> where @@ -520,42 +376,7 @@ pub struct DropTableContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Com pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for DropTableContextExt<'input, 'arena, Tok> -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StatContext } - fn get_rule_index(&self) -> usize { RULE_stat } - fn make_node( - arena: &'arena Arena, - ctx: DropTableContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(StatContextAll::DropTableContext(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a DropTableContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => StatContextAll<'input, 'arena, Tok>) { - StatContextAll::DropTableContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut DropTableContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut StatContextAll<'input, 'arena, Tok>) { - StatContextAll::DropTableContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt StaticDFAParserNodeKind::StatContext, StatContextAll::DropTableContext, DropTableContextExt, RULE_stat } impl<'input, 'arena, Tok> StatContextAttrs<'input, 'arena, Tok> for DropTableContext<'input, 'arena, Tok> where @@ -601,80 +422,65 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn stat(&mut self,) -> Result<&'arena StatContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(StatContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_stat)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, StatContext, RULE_stat, 0, |_parentctx| StatContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena StatContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(23); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(0)?; _sdp } { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - CreateTableContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena CreateTableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(14); - recog.base.match_token(StaticDFA_T__0,&mut recog.err_handler)?; - recog.base.set_state(15); - recog.base.match_token(StaticDFA_T__1,&mut recog.err_handler)?; - recog.base.set_state(16); - recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; - } - } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - CreateViewContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena CreateViewContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(17); - recog.base.match_token(StaticDFA_T__0,&mut recog.err_handler)?; - recog.base.set_state(18); - recog.base.match_token(StaticDFA_T__2,&mut recog.err_handler)?; - recog.base.set_state(19); - recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; - } + recog.base.set_state(23); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(0)?; _sdp } { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + CreateTableContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CreateTableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(14); + recog.base.match_token(StaticDFA_T__0,&mut recog.err_handler)?; + recog.base.set_state(15); + recog.base.match_token(StaticDFA_T__1,&mut recog.err_handler)?; + recog.base.set_state(16); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; } - , - 3 =>{ - /*------- Outer Most Alt 3 -------*/ - recog.base.with_mut_ctx(|ctx| { - DropTableContextExt::copy_from(ctx); - ctx.set_alt_number(3); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena DropTableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(20); - recog.base.match_token(StaticDFA_T__3,&mut recog.err_handler)?; - recog.base.set_state(21); - recog.base.match_token(StaticDFA_T__1,&mut recog.err_handler)?; - recog.base.set_state(22); - recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; - } + } + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + CreateViewContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CreateViewContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(17); + recog.base.match_token(StaticDFA_T__0,&mut recog.err_handler)?; + recog.base.set_state(18); + recog.base.match_token(StaticDFA_T__2,&mut recog.err_handler)?; + recog.base.set_state(19); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; } - - _ => {} } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + , + 3 =>{ + /*------- Outer Most Alt 3 -------*/ + recog.base.with_mut_ctx(|ctx| { + DropTableContextExt::copy_from(ctx); + ctx.set_alt_number(3); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena DropTableContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(20); + recog.base.match_token(StaticDFA_T__3,&mut recog.err_handler)?; + recog.base.set_state(21); + recog.base.match_token(StaticDFA_T__1,&mut recog.err_handler)?; + recog.base.set_state(22); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; + } } + + _ => {} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- expr ---------------- @@ -718,39 +524,7 @@ pub struct ExprContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ExprContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: ExprContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ExprContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ExprContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ExprContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ExprContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled StaticDFAParserNodeKind::ExprContext, ExprContextAll, ExprContextExt, RULE_expr } impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -760,7 +534,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, ) } } - pub trait ExprContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -796,42 +569,7 @@ pub struct CallContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for CallContextExt<'input, 'arena, Tok> -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: CallContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::CallContext(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a CallContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::CallContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut CallContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::CallContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt StaticDFAParserNodeKind::ExprContext, ExprContextAll::CallContext, CallContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for CallContext<'input, 'arena, Tok> where @@ -892,42 +630,7 @@ pub struct RefContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for RefContextExt<'input, 'arena, Tok> -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: RefContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::RefContext(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a RefContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::RefContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut RefContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::RefContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt StaticDFAParserNodeKind::ExprContext, ExprContextAll::RefContext, RefContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for RefContext<'input, 'arena, Tok> where @@ -973,113 +676,52 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn expr(&mut self,) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_expr)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, ExprContext, RULE_expr, 2, |_parentctx| ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena ExprContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(30); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(1)?; _sdp } { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - CallContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena CallContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - /*InvokeRule name*/ - recog.base.set_state(25); - recog.name()?; - recog.base.set_state(26); - recog.base.match_token(StaticDFA_T__4,&mut recog.err_handler)?; - recog.base.set_state(27); - recog.base.match_token(StaticDFA_T__5,&mut recog.err_handler)?; - } - } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - RefContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena RefContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - /*InvokeRule name*/ - recog.base.set_state(29); - recog.name()?; - } + recog.base.set_state(30); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(1)?; _sdp } { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + CallContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena CallContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + /*InvokeRule name*/ + recog.base.set_state(25); + recog.name()?; + recog.base.set_state(26); + recog.base.match_token(StaticDFA_T__4,&mut recog.err_handler)?; + recog.base.set_state(27); + recog.base.match_token(StaticDFA_T__5,&mut recog.err_handler)?; } - - _ => {} } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + RefContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena RefContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + /*InvokeRule name*/ + recog.base.set_state(29); + recog.name()?; + } } + + _ => {} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- name ---------------- pub type NameContextAll<'input, 'arena, Tok = CommonToken<'input>> = NameContext<'input, 'arena, Tok>; -pub type NameContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, NameContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; -#[derive(Debug)] -pub struct NameContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for NameContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::NameContext } - fn get_rule_index(&self) -> usize { RULE_name } - fn make_node( - arena: &'arena Arena, - ctx: NameContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NameContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => NameContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NameContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut NameContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> NameContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, NameContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { StaticDFAParserNodeKind, NameContext, NameContextExt, RULE_name } pub trait NameContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1118,99 +760,38 @@ where if let Some(_node) = self.base.resume_take(RULE_name)? { return Ok(_node.as_rule_context().unwrap()); } - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 4, RULE_name)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, NameContext, RULE_name, 4, |_parentctx| NameContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena NameContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(32); + recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; + recog.base.set_state(37); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + while _la==StaticDFA_T__6 { { - recog.base.set_state(32); + { + recog.base.set_state(33); + recog.base.match_token(StaticDFA_T__6,&mut recog.err_handler)?; + recog.base.set_state(34); recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; - recog.base.set_state(37); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); - while _la==StaticDFA_T__6 { - { - { - recog.base.set_state(33); - recog.base.match_token(StaticDFA_T__6,&mut recog.err_handler)?; - recog.base.set_state(34); - recog.base.match_token(StaticDFA_ID,&mut recog.err_handler)?; - } - } - recog.base.set_state(39); - recog.err_handler.sync(&mut recog.base)?; - _la = recog.base.input.la(1); } } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + recog.base.set_state(39); + recog.err_handler.sync(&mut recog.base)?; + _la = recog.base.input.la(1); + } } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- starLoop ---------------- pub type StarLoopContextAll<'input, 'arena, Tok = CommonToken<'input>> = StarLoopContext<'input, 'arena, Tok>; -pub type StarLoopContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, StarLoopContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; -#[derive(Debug)] -pub struct StarLoopContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for StarLoopContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::StarLoopContext } - fn get_rule_index(&self) -> usize { RULE_starLoop } - fn make_node( - arena: &'arena Arena, - ctx: StarLoopContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a StarLoopContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => StarLoopContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut StarLoopContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut StarLoopContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> StarLoopContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, StarLoopContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { StaticDFAParserNodeKind, StarLoopContext, StarLoopContextExt, RULE_starLoop } pub trait StarLoopContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1232,103 +813,42 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn starLoop(&mut self,) -> Result<&'arena StarLoopContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(StarLoopContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 6, RULE_starLoop)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, StarLoopContext, RULE_starLoop, 6, |_parentctx| StarLoopContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena StarLoopContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(44); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - { - { - recog.base.set_state(40); - recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; - recog.base.set_state(41); - recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; - } - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(44); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + { + { + recog.base.set_state(40); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(41); + recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; } - recog.base.set_state(46); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; - } - recog.base.set_state(47); - recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; - recog.base.set_state(48); - recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + } } + recog.base.set_state(46); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(3)?; _sdp }; + } + recog.base.set_state(47); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(48); + recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- plusLoop ---------------- pub type PlusLoopContextAll<'input, 'arena, Tok = CommonToken<'input>> = PlusLoopContext<'input, 'arena, Tok>; -pub type PlusLoopContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, PlusLoopContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; -#[derive(Debug)] -pub struct PlusLoopContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for PlusLoopContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::PlusLoopContext } - fn get_rule_index(&self) -> usize { RULE_plusLoop } - fn make_node( - arena: &'arena Arena, - ctx: PlusLoopContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a PlusLoopContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => PlusLoopContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut PlusLoopContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut PlusLoopContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> PlusLoopContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, PlusLoopContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { StaticDFAParserNodeKind, PlusLoopContext, PlusLoopContextExt, RULE_plusLoop } pub trait PlusLoopContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1350,107 +870,46 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn plusLoop(&mut self,) -> Result<&'arena PlusLoopContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(PlusLoopContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 8, RULE_plusLoop)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, PlusLoopContext, RULE_plusLoop, 8, |_parentctx| PlusLoopContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena PlusLoopContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(52); - recog.err_handler.sync(&mut recog.base)?; - _alt = 1; - loop { - match _alt { - x if x == 1 => - { - { - recog.base.set_state(50); - recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; - recog.base.set_state(51); - recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; - } - } - - _ => Err(ANTLRError::no_alt(&mut recog.base))? + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(52); + recog.err_handler.sync(&mut recog.base)?; + _alt = 1; + loop { + match _alt { + x if x == 1 => + { + { + recog.base.set_state(50); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(51); + recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; } - recog.base.set_state(54); - recog.err_handler.sync(&mut recog.base)?; - _alt = { let _sdp = recog.base.dfa_predict(4)?; _sdp }; - if _alt==2 || _alt==INVALID_ALT { break } - } - recog.base.set_state(56); - recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; - recog.base.set_state(57); - recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + } + + _ => Err(ANTLRError::no_alt(&mut recog.base))? } + recog.base.set_state(54); + recog.err_handler.sync(&mut recog.base)?; + _alt = { let _sdp = recog.base.dfa_predict(4)?; _sdp }; + if _alt==2 || _alt==INVALID_ALT { break } + } + recog.base.set_state(56); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(57); + recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- opt ---------------- pub type OptContextAll<'input, 'arena, Tok = CommonToken<'input>> = OptContext<'input, 'arena, Tok>; -pub type OptContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, OptContextExt<'input, 'arena, Tok>, StaticDFAParserNodeKind, Tok>; -#[derive(Debug)] -pub struct OptContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for OptContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::OptContext } - fn get_rule_index(&self) -> usize { RULE_opt } - fn make_node( - arena: &'arena Arena, - ctx: OptContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a OptContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => OptContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut OptContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut OptContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> OptContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, OptContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { StaticDFAParserNodeKind, OptContext, OptContextExt, RULE_opt } pub trait OptContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -1472,46 +931,31 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn opt(&mut self,) -> Result<&'arena OptContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(OptContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 10, RULE_opt)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, OptContext, RULE_opt, 10, |_parentctx| OptContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena OptContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(61); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(5)?; _sdp } { - x if x == 1 =>{ - { - recog.base.set_state(59); - recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; - recog.base.set_state(60); - recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(61); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(5)?; _sdp } { + x if x == 1 =>{ + { + recog.base.set_state(59); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(60); + recog.base.match_token(StaticDFA_T__8,&mut recog.err_handler)?; } - - _ => {} - } - recog.base.set_state(63); - recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; - recog.base.set_state(64); - recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; } + + _ => {} + } + recog.base.set_state(63); + recog.base.match_token(StaticDFA_T__7,&mut recog.err_handler)?; + recog.base.set_state(64); + recog.base.match_token(StaticDFA_T__9,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- dup ---------------- @@ -1555,39 +999,7 @@ pub struct DupContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for DupContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::DupContext } - fn get_rule_index(&self) -> usize { RULE_dup } - fn make_node( - arena: &'arena Arena, - ctx: DupContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(DupContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a DupContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => DupContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut DupContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut DupContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled StaticDFAParserNodeKind::DupContext, DupContextAll, DupContextExt, RULE_dup } impl<'input: 'arena, 'arena, Tok: Token + 'input> DupContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena StaticDFAParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut StaticDFAParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -1597,7 +1009,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> DupContextExt<'input, 'arena, ) } } - pub trait DupContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -1629,42 +1040,7 @@ pub struct DupFirstContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Comm pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for DupFirstContextExt<'input, 'arena, Tok> -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::DupContext } - fn get_rule_index(&self) -> usize { RULE_dup } - fn make_node( - arena: &'arena Arena, - ctx: DupFirstContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(DupContextAll::DupFirstContext(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a DupFirstContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => DupContextAll<'input, 'arena, Tok>) { - DupContextAll::DupFirstContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut DupFirstContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut DupContextAll<'input, 'arena, Tok>) { - DupContextAll::DupFirstContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt StaticDFAParserNodeKind::DupContext, DupContextAll::DupFirstContext, DupFirstContextExt, RULE_dup } impl<'input, 'arena, Tok> DupContextAttrs<'input, 'arena, Tok> for DupFirstContext<'input, 'arena, Tok> where @@ -1721,42 +1097,7 @@ pub struct DupSecondContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Com pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for DupSecondContextExt<'input, 'arena, Tok> -{ - type NodeKind = StaticDFAParserNodeKind; - fn node_tag() -> StaticDFAParserNodeKind { StaticDFAParserNodeKind::DupContext } - fn get_rule_index(&self) -> usize { RULE_dup } - fn make_node( - arena: &'arena Arena, - ctx: DupSecondContext<'input, 'arena, Tok>, - ) -> *mut StaticDFAParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(DupContextAll::DupSecondContext(ctx)) - } - fn cast_from<'a>( - node: &'a StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a DupSecondContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => DupContextAll<'input, 'arena, Tok>) { - DupContextAll::DupSecondContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut StaticDFAParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut DupSecondContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut DupContextAll<'input, 'arena, Tok>) { - DupContextAll::DupSecondContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt StaticDFAParserNodeKind::DupContext, DupContextAll::DupSecondContext, DupSecondContextExt, RULE_dup } impl<'input, 'arena, Tok> DupContextAttrs<'input, 'arena, Tok> for DupSecondContext<'input, 'arena, Tok> where @@ -1802,59 +1143,44 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn dup(&mut self,) -> Result<&'arena DupContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(DupContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 12, RULE_dup)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, DupContext, RULE_dup, 12, |_parentctx| DupContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena DupContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - recog.base.set_state(70); - recog.err_handler.sync(&mut recog.base)?; - match { let _sdp = recog.base.dfa_predict(6)?; _sdp } { - 1 =>{ - /*------- Outer Most Alt 1 -------*/ - recog.base.with_mut_ctx(|ctx| { - DupFirstContextExt::copy_from(ctx); - ctx.set_alt_number(1); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena DupFirstContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(66); - recog.base.match_token(StaticDFA_T__10,&mut recog.err_handler)?; - recog.base.set_state(67); - recog.base.match_token(StaticDFA_T__11,&mut recog.err_handler)?; - } - } - , - 2 =>{ - /*------- Outer Most Alt 2 -------*/ - recog.base.with_mut_ctx(|ctx| { - DupSecondContextExt::copy_from(ctx); - ctx.set_alt_number(2); - }); - let _local_ctx_fn = |recog: &Self| -> &'arena DupSecondContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - { - recog.base.set_state(68); - recog.base.match_token(StaticDFA_T__10,&mut recog.err_handler)?; - recog.base.set_state(69); - recog.base.match_token(StaticDFA_T__11,&mut recog.err_handler)?; - } + recog.base.set_state(70); + recog.err_handler.sync(&mut recog.base)?; + match { let _sdp = recog.base.dfa_predict(6)?; _sdp } { + 1 =>{ + /*------- Outer Most Alt 1 -------*/ + recog.base.with_mut_ctx(|ctx| { + DupFirstContextExt::copy_from(ctx); + ctx.set_alt_number(1); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena DupFirstContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(66); + recog.base.match_token(StaticDFA_T__10,&mut recog.err_handler)?; + recog.base.set_state(67); + recog.base.match_token(StaticDFA_T__11,&mut recog.err_handler)?; } - - _ => {} } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; + , + 2 =>{ + /*------- Outer Most Alt 2 -------*/ + recog.base.with_mut_ctx(|ctx| { + DupSecondContextExt::copy_from(ctx); + ctx.set_alt_number(2); + }); + let _local_ctx_fn = |recog: &Self| -> &'arena DupSecondContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + { + recog.base.set_state(68); + recog.base.match_token(StaticDFA_T__10,&mut recog.err_handler)?; + recog.base.set_state(69); + recog.base.match_token(StaticDFA_T__11,&mut recog.err_handler)?; + } } + + _ => {} } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/visitorbasiclexer.rs b/runtime/Rust/tests/gen/visitorbasiclexer.rs index 3d4690465c..5d2facd5c4 100644 --- a/runtime/Rust/tests/gen/visitorbasiclexer.rs +++ b/runtime/Rust/tests/gen/visitorbasiclexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const A:i32=1; @@ -84,27 +67,7 @@ pub struct VisitorBasicLexerActions { impl VisitorBasicLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for VisitorBasicLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for VisitorBasicLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "VisitorBasicLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { VisitorBasicLexerActions, "VisitorBasicLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/visitorbasicparser.rs b/runtime/Rust/tests/gen/visitorbasicparser.rs index ccdc82f3bc..10f4e6ee53 100644 --- a/runtime/Rust/tests/gen/visitorbasicparser.rs +++ b/runtime/Rust/tests/gen/visitorbasicparser.rs @@ -6,36 +6,11 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::visitorbasiclistener::*; use super::visitorbasicvisitor::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const VisitorBasic_A:i32=1; pub const VisitorBasic_EOF:i32=EOF; @@ -157,75 +132,13 @@ pub struct VisitorBasicParserExt<'input, 'arena> { impl<'input, 'arena> VisitorBasicParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for VisitorBasicParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_parser_recog! { VisitorBasicParserExt, VisitorBasicParserNodeKind, "VisitorBasic.g4" } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for VisitorBasicParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "VisitorBasic.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } -} //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, VisitorBasicParserNodeKind, Tok>; dbt_antlr4::impl_visitable! { VisitorBasicVisitor::SContext(visit_s) } -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = VisitorBasicParserNodeKind; - fn node_tag() -> VisitorBasicParserNodeKind { VisitorBasicParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut VisitorBasicParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a VisitorBasicParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut VisitorBasicParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena VisitorBasicParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut VisitorBasicParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { VisitorBasicParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -263,32 +176,17 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - recog.base.set_state(2); - recog.base.match_token(VisitorBasic_A,&mut recog.err_handler)?; - recog.base.set_state(3); - recog.base.match_token(VisitorBasic_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + recog.base.set_state(2); + recog.base.match_token(VisitorBasic_A,&mut recog.err_handler)?; + recog.base.set_state(3); + recog.base.match_token(VisitorBasic_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } diff --git a/runtime/Rust/tests/gen/visitorcalclexer.rs b/runtime/Rust/tests/gen/visitorcalclexer.rs index f531e47aa5..bf629320f2 100644 --- a/runtime/Rust/tests/gen/visitorcalclexer.rs +++ b/runtime/Rust/tests/gen/visitorcalclexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const INT:i32=1; @@ -90,27 +73,7 @@ pub struct VisitorCalcLexerActions { impl VisitorCalcLexerActions { } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for VisitorCalcLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, - {} - -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for VisitorCalcLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "VisitorCalcLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { VisitorCalcLexerActions, "VisitorCalcLexer.g4" } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/runtime/Rust/tests/gen/visitorcalcparser.rs b/runtime/Rust/tests/gen/visitorcalcparser.rs index cef22256ee..34c33d6fb2 100644 --- a/runtime/Rust/tests/gen/visitorcalcparser.rs +++ b/runtime/Rust/tests/gen/visitorcalcparser.rs @@ -6,36 +6,11 @@ #![allow(nonstandard_style)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::visitorcalclistener::*; use super::visitorcalcvisitor::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - dbt_antlr4::check_version!("2","0"); pub const VisitorCalc_INT:i32=1; pub const VisitorCalc_MUL:i32=2; @@ -165,32 +140,7 @@ pub struct VisitorCalcParserExt<'input, 'arena> { impl<'input, 'arena> VisitorCalcParserExt<'input, 'arena> { } -impl<'input, 'arena, Input, TF> ParserRecog<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for VisitorCalcParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} - -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseParserType<'input, 'arena, Input, TF>, TF::Tok> for VisitorCalcParserExt<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory<'input, 'arena> + 'arena, - Input: TokenStream<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "VisitorCalc.g4" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option<&'arena VisitorCalcParserNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - 1 => VisitorCalcParser::<'input, 'arena, Input, TF>::expr_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog), - _ => true - } - } -} +dbt_antlr4::impl_parser_recog! { VisitorCalcParserExt, VisitorCalcParserNodeKind, "VisitorCalc.g4"; sempred (VisitorCalcParserNode<'input, 'arena, TF::Tok>, VisitorCalcParser) { 1 => expr_sempred, } } impl<'input, 'arena, Input, TF> VisitorCalcParser<'input, 'arena, Input, TF> where @@ -214,54 +164,8 @@ where //------------------- s ---------------- pub type SContextAll<'input, 'arena, Tok = CommonToken<'input>> = SContext<'input, 'arena, Tok>; -pub type SContext<'input, 'arena, Tok = CommonToken<'input>> = BaseParserRuleContext<'input, 'arena, SContextExt<'input, 'arena, Tok>, VisitorCalcParserNodeKind, Tok>; dbt_antlr4::impl_visitable! { VisitorCalcVisitor::SContext(visit_s) } -#[derive(Debug)] -pub struct SContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonToken<'input>> { - ph: PhantomData<(&'arena (), &'input Tok)>, -} - -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for SContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = VisitorCalcParserNodeKind; - fn node_tag() -> VisitorCalcParserNodeKind { VisitorCalcParserNodeKind::SContext } - fn get_rule_index(&self) -> usize { RULE_s } - fn make_node( - arena: &'arena Arena, - ctx: SContext<'input, 'arena, Tok>, - ) -> *mut VisitorCalcParserNode<'input, 'arena, Tok> { - arena.alloc_zeroed_node(ctx)} - fn cast_from<'a>( - node: &'a VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => SContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut SContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut SContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - -impl<'input: 'arena, 'arena, Tok: Token + 'input> SContextExt<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option<&'arena VisitorCalcParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut VisitorCalcParserNode<'input, 'arena, Tok>, ANTLRError> - { - BaseParserRuleContext::create(arena, parent, invoking_state, SContextExt { - ph: PhantomData - } - ) - } -} +dbt_antlr4::impl_ctx! { VisitorCalcParserNodeKind, SContext, SContextExt, RULE_s } pub trait SContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where @@ -295,33 +199,18 @@ where Input: TokenStream<'input, 'arena, TF> + 'arena, { pub fn s(&mut self,) -> Result<&'arena SContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - recog.base.enter_rule(SContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 0, RULE_s)?; + dbt_antlr4::parse_rule!(recog = self, _parentctx, SContext, RULE_s, 0, |_parentctx| SContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); { let _local_ctx_fn = |recog: &Self| -> &'arena SContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result<(), ANTLRError> = (|| { - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - /*InvokeRule expr*/ - recog.base.set_state(4); - recog.expr_rec(0)?; - recog.base.set_state(5); - recog.base.match_token(VisitorCalc_EOF,&mut recog.err_handler)?; - } - Ok(()) - })(); - match result { - Ok(_)=>{}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?; - } + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + /*InvokeRule expr*/ + recog.base.set_state(4); + recog.expr_rec(0)?; + recog.base.set_state(5); + recog.base.match_token(VisitorCalc_EOF,&mut recog.err_handler)?; } - recog.base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + }) } } //------------------- expr ---------------- @@ -368,39 +257,7 @@ pub struct ExprContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTo ph: PhantomData<(&'arena (), &'input Tok)>, } -impl<'input: 'arena, 'arena, Tok> CustomRuleContext<'input, 'arena, Tok> for ExprContextExt<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = VisitorCalcParserNodeKind; - fn node_tag() -> VisitorCalcParserNodeKind { VisitorCalcParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: ExprContext<'input, 'arena, Tok>, - ) -> *mut VisitorCalcParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::Error(ctx)) - } - fn cast_from<'a>( - node: &'a VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a ExprContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => ExprContext<'input, 'arena, Tok>)) - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut ExprContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut ExprContext<'input, 'arena, Tok>)) - } else { - None - } - } -} - +dbt_antlr4::impl_ctx! { @labeled VisitorCalcParserNodeKind::ExprContext, ExprContextAll, ExprContextExt, RULE_expr } impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, Tok>{ fn create(arena: &'arena Arena, parent: Option<&'arena VisitorCalcParserNode<'input, 'arena, Tok>>, invoking_state: i32) -> Result<&'arena mut VisitorCalcParserNode<'input, 'arena, Tok>, ANTLRError> { @@ -410,7 +267,6 @@ impl<'input: 'arena, 'arena, Tok: Token + 'input> ExprContextExt<'input, 'arena, ) } } - pub trait ExprContextAttrs<'input, 'arena, Tok>: ParserRuleContext<'input, 'arena> where 'input: 'arena, @@ -466,42 +322,7 @@ pub struct AddContextExt<'input: 'arena, 'arena, Tok: Token + 'input = CommonTok pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for AddContextExt<'input, 'arena, Tok> -{ - type NodeKind = VisitorCalcParserNodeKind; - fn node_tag() -> VisitorCalcParserNodeKind { VisitorCalcParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: AddContext<'input, 'arena, Tok>, - ) -> *mut VisitorCalcParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::AddContext(ctx)) - } - fn cast_from<'a>( - node: &'a VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut AddContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::AddContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt VisitorCalcParserNodeKind::ExprContext, ExprContextAll::AddContext, AddContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for AddContext<'input, 'arena, Tok> where @@ -566,42 +387,7 @@ pub struct NumberContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Common pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for NumberContextExt<'input, 'arena, Tok> -{ - type NodeKind = VisitorCalcParserNodeKind; - fn node_tag() -> VisitorCalcParserNodeKind { VisitorCalcParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: NumberContext<'input, 'arena, Tok>, - ) -> *mut VisitorCalcParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::NumberContext(ctx)) - } - fn cast_from<'a>( - node: &'a VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a NumberContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::NumberContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut NumberContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::NumberContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt VisitorCalcParserNodeKind::ExprContext, ExprContextAll::NumberContext, NumberContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for NumberContext<'input, 'arena, Tok> where @@ -682,42 +468,7 @@ pub struct MultiplyContextExt<'input: 'arena, 'arena, Tok: Token + 'input = Comm pd: PhantomData<(&'arena (), &'input Tok)> } -impl<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext<'input, 'arena, Tok> for MultiplyContextExt<'input, 'arena, Tok> -{ - type NodeKind = VisitorCalcParserNodeKind; - fn node_tag() -> VisitorCalcParserNodeKind { VisitorCalcParserNodeKind::ExprContext } - fn get_rule_index(&self) -> usize { RULE_expr } - fn make_node( - arena: &'arena Arena, - ctx: MultiplyContext<'input, 'arena, Tok>, - ) -> *mut VisitorCalcParserNode<'input, 'arena, Tok> { - arena.alloc_labeled_node(ExprContextAll::MultiplyContext(ctx)) - } - fn cast_from<'a>( - node: &'a VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a MultiplyContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::MultiplyContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut<'a>( - node: &'a mut VisitorCalcParserNode<'input, 'arena, Tok>, - ) -> Option<&'a mut MultiplyContext<'input, 'arena, Tok>> { - if node.node_tag() == >::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ExprContextAll<'input, 'arena, Tok>) { - ExprContextAll::MultiplyContext(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt VisitorCalcParserNodeKind::ExprContext, ExprContextAll::MultiplyContext, MultiplyContextExt, RULE_expr } impl<'input, 'arena, Tok> ExprContextAttrs<'input, 'arena, Tok> for MultiplyContext<'input, 'arena, Tok> where @@ -768,114 +519,99 @@ where } fn expr_rec(&mut self, _p: i32) -> Result<&'arena ExprContextAll<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = recog.base.take_ctx(); - let _parentState = recog.base.get_state(); - recog.base.enter_recursion_rule(ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state())?, 2, RULE_expr, _p)?; + dbt_antlr4::parse_rule!(rec recog = self, _parentctx, _parentState, ExprContext, RULE_expr, 2, |_parentctx| ExprContextExt::create(recog.get_arena(), _parentctx, recog.get_state()); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena ExprContext {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = 2; let mut _la: i32 = -1; - let result: Result<(), ANTLRError> = (|| { - let mut _alt: i32; - /*------- Outer Most Alt 1 -------*/ - unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } - { - { - recog.base.with_mut_ctx(|ctx| { NumberContextExt::copy_from(ctx); }); - let _local_ctx_fn = |recog: &Self| -> &'arena NumberContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(8); - recog.base.match_token(VisitorCalc_INT,&mut recog.err_handler)?; - } - let tmp = recog.input.lt(-1); - recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); - recog.base.set_state(18); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(1,&mut recog.base)?; - while { _alt!=2 && _alt!=INVALID_ALT } { - if _alt==1 { - recog.trigger_exit_rule_event()?; - { - recog.base.set_state(16); - recog.err_handler.sync(&mut recog.base)?; - match recog.get_interpreter().adaptive_predict(0,&mut recog.base)? { - 1 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - MultiplyContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; - let _local_ctx_fn = |recog: &Self| -> &'arena MultiplyContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(10); - if !({recog.precpred(None, 2)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; - } - recog.base.set_state(11); - _la = recog.base.input.la(1); - if { !(_la==VisitorCalc_MUL || _la==VisitorCalc_DIV) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule expr*/ - recog.base.set_state(12); - recog.expr_rec(3)?; - } + let mut _alt: i32; + /*------- Outer Most Alt 1 -------*/ + unsafe { recog.ctx_mut().unwrap().set_alt_number(1); } + { + { + recog.base.with_mut_ctx(|ctx| { NumberContextExt::copy_from(ctx); }); + let _local_ctx_fn = |recog: &Self| -> &'arena NumberContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(8); + recog.base.match_token(VisitorCalc_INT,&mut recog.err_handler)?; + } + let tmp = recog.input.lt(-1); + recog.base.with_mut_ctx(|ctx| { ctx.set_stop(tmp.map(|t| t as _)); }); + recog.base.set_state(18); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(1,&mut recog.base)?; + while { _alt!=2 && _alt!=INVALID_ALT } { + if _alt==1 { + recog.trigger_exit_rule_event()?; + { + recog.base.set_state(16); + recog.err_handler.sync(&mut recog.base)?; + match recog.get_interpreter().adaptive_predict(0,&mut recog.base)? { + 1 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + MultiplyContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena MultiplyContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(10); + if !({recog.precpred(None, 2)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 2)".to_owned()), None))?; } - , - 2 =>{ - { - /*recRuleLabeledAltStartAction*/ - let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; - AddContextExt::copy_from(tmp); - let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; - let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; - - recog.base.set_state(13); - if !({recog.precpred(None, 1)}) { - Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; - } - recog.base.set_state(14); - _la = recog.base.input.la(1); - if { !(_la==VisitorCalc_ADD || _la==VisitorCalc_SUB) } { - recog.err_handler.recover_inline(&mut recog.base)?; - } - else { - if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; - recog.err_handler.report_match(&mut recog.base); - recog.base.consume(&mut recog.err_handler)?; - } - /*InvokeRule expr*/ - recog.base.set_state(15); - recog.expr_rec(2)?; - } + recog.base.set_state(11); + _la = recog.base.input.la(1); + if { !(_la==VisitorCalc_MUL || _la==VisitorCalc_DIV) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule expr*/ + recog.base.set_state(12); + recog.expr_rec(3)?; } - - _ => {} } - } + , + 2 =>{ + { + /*recRuleLabeledAltStartAction*/ + let tmp = ExprContextExt::create(recog.get_arena(), _parentctx, _parentState)?; + AddContextExt::copy_from(tmp); + let _prevctx = recog.push_new_recursion_context(tmp, _startState, RULE_expr)?; + let _local_ctx_fn = |recog: &Self| -> &'arena AddContext {recog.ctx().unwrap().as_rule_context().unwrap()}; + + recog.base.set_state(13); + if !({recog.precpred(None, 1)}) { + Err(ANTLRError::failed_predicate(&mut recog.base, Some("recog.precpred(None, 1)".to_owned()), None))?; + } + recog.base.set_state(14); + _la = recog.base.input.la(1); + if { !(_la==VisitorCalc_ADD || _la==VisitorCalc_SUB) } { + recog.err_handler.recover_inline(&mut recog.base)?; + } + else { + if recog.base.input.la(1)==TOKEN_EOF { recog.base.matched_eof = true }; + recog.err_handler.report_match(&mut recog.base); + recog.base.consume(&mut recog.err_handler)?; + } + /*InvokeRule expr*/ + recog.base.set_state(15); + recog.expr_rec(2)?; + } + } + + _ => {} } - recog.base.set_state(20); - recog.err_handler.sync(&mut recog.base)?; - _alt = recog.get_interpreter().adaptive_predict(1,&mut recog.base)?; - } + } } - Ok(()) - })(); - match result { - Ok(_) => {}, - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - recog.err_handler.report_error(&mut recog.base, re); - recog.err_handler.recover(&mut recog.base, re)?;} + recog.base.set_state(20); + recog.err_handler.sync(&mut recog.base)?; + _alt = recog.get_interpreter().adaptive_predict(1,&mut recog.base)?; + } } - recog.base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + }) } } diff --git a/runtime/Rust/tests/gen/xmllexer.rs b/runtime/Rust/tests/gen/xmllexer.rs index 39087100b8..24148bd195 100644 --- a/runtime/Rust/tests/gen/xmllexer.rs +++ b/runtime/Rust/tests/gen/xmllexer.rs @@ -5,25 +5,8 @@ #![allow(unused_variables)] #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; dbt_antlr4::check_version!("2","0"); pub const COMMENT:i32=1; @@ -132,39 +115,7 @@ impl XMLLexerActions { } } -impl<'input, 'arena, Input, TF> Actions<'input, 'arena, BaseLexerType<'input, 'arena, Input, TF>, TF::Tok> - for XMLLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn action(_localctx: Option<&EmptyRuleNode<'input, 'arena, TF::Tok>>, rule_index: i32, action_index: i32, recog:&mut BaseLexerType<'input, 'arena, Input, TF>) { - match rule_index { - 10 => XMLLexerActions::CLOSE_action(action_index, recog), - _ => {} - } - } - fn sempred(_localctx: Option<&EmptyRuleNode<'input, 'arena, TF::Tok>>, rule_index: i32, pred_index: i32, recog:&mut BaseLexerType<'input, 'arena, Input, TF>) -> bool { - match rule_index { - 0 => XMLLexerActions::COMMENT_sempred(pred_index, recog), - _ => true - } - } -} -impl<'input, 'arena, Input, TF> LexerRecog<'input, 'arena, TF, BaseLexerType<'input, 'arena, Input, TF>> - for XMLLexerActions -where - 'input: 'arena, - Input: CharStream<'input>, - TF: TokenFactory<'input, 'arena> + 'arena, -{ - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { "XMLLexer.g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { XMLLexerActions, "XMLLexer.g4"; action { 10 => CLOSE_action, }; sempred { 0 => COMMENT_sempred, } } static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index 205ba1146a..153fdf8848 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -58,28 +58,8 @@ ParserFile(file, parser, namedActions, contextSuperClass) ::= << #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::parser::{Parser, BaseParser, ParserRecog, ListenerId}; -use dbt_antlr4::token::CommonToken; -use dbt_antlr4::token_stream::TokenStream; -use dbt_antlr4::TokenSource; -use dbt_antlr4::parser_atn_simulator::ParserATNSimulator; -use dbt_antlr4::errors::ANTLRError; -use dbt_antlr4::rule_context::{CustomRuleContext, RuleContext}; -use dbt_antlr4::recognizer::{Recognizer,Actions}; -use dbt_antlr4::atn_config_set::ATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::ParserATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::atn::{ATN, INVALID_ALT}; -use dbt_antlr4::error_strategy::{DefaultErrorStrategy, ErrorStrategyDelegate, ErrorStrategy}; -use dbt_antlr4::parser_rule_context::{BaseParserRuleContext, ParserRuleContext}; -use dbt_antlr4::tree::*; -use dbt_antlr4::token::{TOKEN_EOF,Token}; -use dbt_antlr4::int_stream::EOF; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; -use dbt_antlr4::token_factory::TokenFactory; use super::listener::*; @@ -87,11 +67,6 @@ use super::listener::*; use super::visitor::*; -use std::marker::PhantomData; -use std::sync::LazyLock; -use std::rc::Rc; -use std::ops::{DerefMut, Deref}; - >> @@ -371,34 +346,9 @@ impl\<'input, 'arena> Ext\<'input, 'arena> { } -impl\<'input, 'arena, Input, TF\> ParserRecog\<'input, 'arena, BaseParserType\<'input, 'arena, Input, TF>, TF::Tok\> for Ext\<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory\<'input, 'arena> + 'arena, - Input: TokenStream\<'input, 'arena, TF> + 'arena { - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_parser_recog! { Ext, NodeKind, ""; sempred (Node\<'input, 'arena, TF::Tok\>, ) { => _sempred,}; separator="\n"> } } -impl\<'input, 'arena, Input, TF\> Actions\<'input, 'arena, BaseParserType\<'input, 'arena, Input, TF>, TF::Tok\> for Ext\<'input, 'arena> -where - 'input: 'arena, - TF: TokenFactory\<'input, 'arena> + 'arena, - Input: TokenStream\<'input, 'arena, TF> + 'arena, -{ - fn get_grammar_file_name(&self) -> & str{ "" } - fn get_rule_names(&self) -> &[& str] { &ruleNames } - fn get_vocabulary(&self) -> &dyn Vocabulary { &**VOCABULARY } - fn sempred(_localctx: Option\<&'arena Node\<'input, 'arena, TF::Tok\>\>, rule_index: i32, pred_index: i32, - recog:&mut BaseParserType\<'input, 'arena, Input, TF> - ) -> bool { - match rule_index { - => ::\<'input, 'arena, Input, TF>::_sempred(_localctx.and_then(|x| x.as_rule_context()), pred_index, recog),}; separator="\n"> - _ => true - } - } -} - impl\<'input, 'arena, Input, TF> \<'input, 'arena, Input, TF> where 'input: 'arena, @@ -406,8 +356,8 @@ where Input: TokenStream\<'input, 'arena, TF> + 'arena, { - } + @@ -424,29 +374,6 @@ pub const _SYMBOLIC_NAMES: [Option\<&'static str>;] = [ static VOCABULARY: LazyLock\\> = LazyLock::new(|| Box::new(VocabularyImpl::new(_LITERAL_NAMES.iter(), _SYMBOLIC_NAMES.iter(), None))); >> -dumpLexerActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= << -{ - - fn action(_localctx: Option\<&EmptyRuleNode\<'input, 'arena, TF::Tok\>\>, rule_index: i32, action_index: i32, recog:&mut BaseLexerType\<'input, 'arena, Input, TF>) { - match rule_index { - => Actions::_action(action_index, recog), }; separator="\n"> - _ => {} - } - } - - - fn sempred(_localctx: Option\<&EmptyRuleNode\<'input, 'arena, TF::Tok\>\>, rule_index: i32, pred_index: i32, recog:&mut BaseLexerType\<'input, 'arena, Input, TF>) -> bool { - match rule_index { - => Actions::_sempred(pred_index, recog), }; separator="\n"> - _ => true - } - } - -} ->> - parser_ctor(p) ::= << >> RuleActionFunction(r, actions) ::= << @@ -539,31 +466,14 @@ where { }>pub fn (&mut self,) -> Result\<&'arena All\<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = .base.take_ctx(); - .base.enter_rule(Ext::create(.get_arena(), _parentctx, .get_state()}>)?, , RULE_)?; + dbt_antlr4::parse_rule!(catch recog = self, _parentctx, \, RULE_, , |_parentctx| Ext::create(recog.get_arena(), _parentctx, recog.get_state()}>); { let _local_ctx_fn = |recog: &Self| -> &'arena \ {recog.ctx().unwrap().as_rule_context().unwrap()}; - let result: Result\<(), ANTLRError> = (|| { - let mut _alt: i32; - - - Ok(()) - })(); - match result { - Ok(_)=>{}, - - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re) => { - .err_handler.report_error(&mut .base, re); - .err_handler.recover(&mut .base, re)?; - } - } - - .base.exit_rule().map(|ctx: &'arena _| { ctx.as_rule_context().unwrap() }) - }) + let mut _alt: i32; + + + }; []; []) } } >> @@ -586,37 +496,18 @@ where self._rec(0}>) } - fn _rec(&mut self, _p: i32}>) -> Result\<&'arena All\<'input, 'arena, TF::Tok\>, ANTLRError> { + fn _rec(&mut self, _p: i32}>) -> Result\<&'arena All\<'input, 'arena, TF::Tok>, ANTLRError> { - dbt_antlr4::maybe_grow_stack!({ - let recog = self; - let _parentctx = .base.take_ctx(); - let _parentState = .base.get_state(); - .base.enter_recursion_rule(Ext::create(.get_arena(), _parentctx, .get_state()}>)?, , RULE_, _p)?; + dbt_antlr4::parse_rule!(catch rec recog = self, _parentctx, _parentState, \, RULE_, , |_parentctx| Ext::create(recog.get_arena(), _parentctx, recog.get_state()}>); _p; { let _local_ctx_fn = |recog: &Self| -> &'arena \ {recog.ctx().unwrap().as_rule_context().unwrap()}; let _startState = ; - let result: Result\<(), ANTLRError> = (|| { - let mut _alt: i32; - - - - Ok(()) - })(); - match result { - Ok(_) => {}, - - - - Err(e) if !e.is_recoverable() => return Err(e), - Err(ref re)=>{ - .err_handler.report_error(&mut .base, re); - .err_handler.recover(&mut .base, re)?;} - } - - .base.unroll_recursion_context(_parentctx).map(|ctx| { ctx.as_rule_context().unwrap() } ) - }) + let mut _alt: i32; + + + + }; []; []) } } >> @@ -1185,6 +1076,7 @@ CaptureNextToken(d) ::= " = .base.input.lt(1).unwrap();" CaptureNextTokenType(d) ::= " = .base.input.la(1);" StructDecl(struct,ctorAttrs,attrs,getters,dispatchMethods,interfaces,extensionMembers,signatures) ::= << + pub type \<'input, 'arena, Tok = CommonToken\<'input>\> = BaseParserRuleContext\<'input, 'arena, Ext\<'input, 'arena, Tok\>, NodeKind, Tok\>; dbt_antlr4::impl_visitable! { Visitor::(visit_) } #[derive(Debug)] @@ -1193,44 +1085,14 @@ pub struct Ext\<'input: 'arena, 'arena, Tok: Token + 'input ph: PhantomData\<(&'arena (), &'input Tok)\>, } -impl\<'input: 'arena, 'arena, Tok> CustomRuleContext\<'input, 'arena, Tok> for Ext\<'input, 'arena, Tok> -where - Tok: Token + 'input, -{ - type NodeKind = NodeKind; - fn node_tag() -> NodeKind { NodeKind::Context } - fn get_rule_index(&self) -> usize { RULE_ } - fn make_node( - arena: &'arena Arena, - ctx: \<'input, 'arena, Tok\>, - ) -> *mut Node\<'input, 'arena, Tok\> { - arena.alloc_labeled_node(All::Error(ctx)) +dbt_antlr4::impl_ctx! { @labeled NodeKind::Context, All, Ext, RULE_ } - arena.alloc_zeroed_node(ctx) - } - fn cast_from\<'a>( - node: &'a Node\<'input, 'arena, Tok\>, - ) -> Option\<&'a \<'input, 'arena, Tok\>\> { - if node.node_tag() == \\>::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => \<'input, 'arena, Tok\>)) - } else { - None - } - } - fn cast_from_mut\<'a>( - node: &'a mut Node\<'input, 'arena, Tok\>, - ) -> Option\<&'a mut \<'input, 'arena, Tok\>\> { - if node.node_tag() == \\>::node_tag() { - Some(dbt_antlr4::cast_unchecked!(node.ctx_ptr() => mut \<'input, 'arena, Tok\>)) - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @plain NodeKind::Context, Ext, RULE_ } + impl\<'input: 'arena, 'arena, Tok: Token + 'input> Ext\<'input, 'arena, Tok>{ - fn create(arena: &'arena Arena, parent: Option\<&'arena Node\<'input, 'arena, Tok\>\>, invoking_state: i32}>) -> Result\<&'arena mut Node\<'input, 'arena, Tok>, ANTLRError\> + fn create(arena: &'arena Arena, parent: Option\<&'arena Node\<'input, 'arena, Tok\>\>, invoking_state: i32}>) -> Result\<&'arena mut Node\<'input, 'arena, Tok\>, ANTLRError\> { = ; }> @@ -1249,6 +1111,10 @@ impl\<'input: 'arena, 'arena, Tok: Token + 'input> Ext\<'inp ) } } + +dbt_antlr4::impl_visitable! { Visitor::(visit_) } +dbt_antlr4::impl_ctx! { NodeKind, , Ext, RULE_ } + pub trait Attrs\<'input, 'arena, Tok>: ParserRuleContext\<'input, 'arena> where @@ -1295,42 +1161,7 @@ pub struct Ext\<'input: 'arena, 'arena, Tok: Token + 'input pd: PhantomData\<(&'arena (), &'input Tok)\> } -impl\<'input: 'arena, 'arena, Tok: Token + 'input> CustomRuleContext\<'input, 'arena, Tok> for Ext\<'input, 'arena, Tok> -{ - type NodeKind = NodeKind; - fn node_tag() -> NodeKind { NodeKind::Context } - fn get_rule_index(&self) -> usize { RULE_ } - fn make_node( - arena: &'arena Arena, - ctx: \<'input, 'arena, Tok>, - ) -> *mut Node\<'input, 'arena, Tok> { - arena.alloc_labeled_node(ContextAll::(ctx)) - } - fn cast_from\<'a>( - node: &'a Node\<'input, 'arena, Tok>, - ) -> Option\<&'a \<'input, 'arena, Tok\>\> { - if node.node_tag() == \\>::node_tag() { - match dbt_antlr4::cast_unchecked!(node => ContextAll\<'input, 'arena, Tok\>) { - ContextAll::(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } - fn cast_from_mut\<'a>( - node: &'a mut Node\<'input, 'arena, Tok>, - ) -> Option\<&'a mut \<'input, 'arena, Tok\>\> { - if node.node_tag() == \\>::node_tag() { - match dbt_antlr4::cast_unchecked!(node => mut ContextAll\<'input, 'arena, Tok\>) { - ContextAll::(ctx) => Some(ctx), - _ => None - } - } else { - None - } - } -} +dbt_antlr4::impl_ctx! { @alt NodeKind::Context, ContextAll::, Ext, RULE_ } impl\<'input, 'arena, Tok> ContextAttrs\<'input, 'arena, Tok> for \<'input, 'arena, Tok> where @@ -1459,25 +1290,8 @@ LexerFile(lexerFile, lexer, namedActions) ::= << #![allow(unused_braces)] #![allow(unused_parens)] -use dbt_antlr4::Arena; -use dbt_antlr4::atn::ATN; -use dbt_antlr4::char_stream::CharStream; -use dbt_antlr4::int_stream::IntStream; -use dbt_antlr4::lexer::{BaseLexer, LexerRecog, Lexer as _}; -use dbt_antlr4::atn_config_set::LexerATNConfigSet; -use dbt_antlr4::atn_deserializer::ATNDeserializer; -use dbt_antlr4::atn_simulator::BaseATNSimulator; +use dbt_antlr4::prelude::*; use dbt_antlr4::atn_simulator::LexerATNSimulatorManager as ATNSimulatorManager; -use dbt_antlr4::TokenSource; -use dbt_antlr4::lexer_atn_simulator::{LexerATNSimulator, ILexerATNSimulator}; -use dbt_antlr4::PredictionContextCache; -use dbt_antlr4::recognizer::Actions; -use dbt_antlr4::token_factory::{CommonTokenFactory, TokenFactory}; -use dbt_antlr4::rule_context::{BaseRuleContext,EmptyNodeKind,EmptyCustomRuleContext,EmptyRuleNode}; -use dbt_antlr4::vocabulary::{Vocabulary,VocabularyImpl}; - -use std::ops::{DerefMut, Deref}; -use std::sync::LazyLock; >> @@ -1547,30 +1361,7 @@ impl Actions { } -impl\<'input, 'arena, Input, TF\> Actions\<'input, 'arena, BaseLexerType\<'input, 'arena, Input, TF\>, TF::Tok\> - for Actions -where - 'input: 'arena, - Input: CharStream\<'input>, - TF: TokenFactory\<'input, 'arena> + 'arena, - - {} - - -impl\<'input, 'arena, Input, TF\> LexerRecog\<'input, 'arena, TF, BaseLexerType\<'input, 'arena, Input, TF\>\> - for Actions -where - 'input: 'arena, - Input: CharStream\<'input>, - TF: TokenFactory\<'input, 'arena> + 'arena, -{ - - fn get_rule_names(&self) -> &'static [&'static str] { &ruleNames } - fn get_literal_names(&self) -> &[Option\<&str>] { &_LITERAL_NAMES } - fn get_symbolic_names(&self) -> &[Option\<&str>] { &_SYMBOLIC_NAMES } - fn get_grammar_file_name(&self) -> &'static str { ".g4" } - fn get_atn_simulator_man(&self) -> &'static ATNSimulatorManager { &ATN_SIMULATOR_MANAGER } -} +dbt_antlr4::impl_lexer_recog! { Actions, ".g4"; action { => _action,}; separator="\n"> }; sempred { => _sempred,}; separator="\n"> }; extend { } } >> From 451fe2cc74eb54237d991a6ce4e210ef2a0a49af Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Wed, 29 Jul 2026 19:19:28 -0400 Subject: [PATCH 39/48] Guarded-iterate: stack-guarded resolution of iterate/exit conflicts vetoed only on foreign consumption The enter/exit substitution of a precedence-class build resolves an iterate/exit conflict to iterate whenever the exit lineage's consumption stays in the loop discipline; it vetoes when exit consumed in a foreign frame (FOREIGN_CONSUME_TAINT). The canonical shape is Trino's BETWEEN separator AND colliding with the booleanExpression loop's own AND (d=238): the phantom exit descends into predicate through a re-entered booleanExpression, a frame no real stack can carry at that decision (BETWEEN's operands are valueExpression, and every nesting path owes tokens the lookahead does not offer). This change gives such conflicts the guarded-take treatment, generalized from optional postfix to precedence loops. When the substitution vetoes solely on foreign consumption (iterate attested real, no obligations), the foreign-marking move records the consumption's root positions (the consuming state, plus call sites of non-loop context frames - loop-block frames play the mirror role the block end plays for the postfix guard) and the state is admitted as a guarded-iterate candidate. A new finalizeGuardedIterates resolves eligible states (every foreign exit config rooted, no unrooted widened exits, iterate attested) to GUARDED accepts with the same danger/pass stack chase as guarded-take - defer is adaptivePredict, so resolution is sound by construction - and upgrades to plain iterate accepts when no invoking state's follow region reaches a root (the foreign consumer is unreachable on every stack). The guard chase is precise about token obligations: nested boolean frames behind ')' / THEN / END never trip it, while BetweenExpr's lambda corners (ID '->' b, a value-position recursion into the boolean rule) trip it exactly where exit genuinely wins. Effect (full-dialect sweep vs rpt4): - Trino booleanExpression d=238: 2e -> 0 (every loop-continuation AND was one adaptivePredict; pred-corpus d=238 fires 190 -> 0, total 370 -> 180); static-only 360 -> 361 - Bigquery d=312: 2e -> 0; Databricks d=380: 164e -> 90e; Duckdb d=335: 118e -> 57e; Redshift d=312: 125e -> 57e; Snowflake d=600: 70e -> 18e - total escapes 10488 -> 10174 Perf: WHERE A=1 AND B=2 AND C=3 AND D=4 parses 5.25us static vs 21.3us adaptive (4.1x; was one escape per AND). Verification: cargo 57/0 (witness corners incl. lambda defers), tool-testsuite 694/0, runtime-testsuite rust.** 707/707; Java tree diffs: Trino 3208/2, Bigquery 2890/3 (both the known :: error-path class), Duckdb/Redshift/ClickHouse 2890/0; Rust twins: Databricks 1998/0, Snowflake 1998/2 (pre-existing error-recovery count class, oracle-proven with the pre-change tool). Signed-off-by: Bo Lin --- runtime/Rust/grammars/BetweenExpr.g4 | 10 +- runtime/Rust/tests/gen/betweenexprparser.rs | 17 +- .../antlr/v4/analysis/DecisionClassifier.java | 262 +++++++++++++++--- 3 files changed, 245 insertions(+), 44 deletions(-) diff --git a/runtime/Rust/grammars/BetweenExpr.g4 b/runtime/Rust/grammars/BetweenExpr.g4 index 6457437bcf..2a71084424 100644 --- a/runtime/Rust/grammars/BetweenExpr.g4 +++ b/runtime/Rust/grammars/BetweenExpr.g4 @@ -10,7 +10,9 @@ // after `a BETWEEN b AND c`, the boolean loop sees AND and must decide // iterate (a new boolean operand) vs exit (the AND belongs to an enclosing // construct). Statically provable shapes of this conflict resolve in the -// class tables of the b-loop decision; the rest escape to adaptivePredict. +// class tables of the b-loop decision; the rest resolve to iterate under +// a real-stack guard (the guarded-iterate escape) that defers to +// adaptivePredict exactly when the stack can make the exit reading viable. // // The grammar also carries 'NOT'? BETWEEN, whose lookahead collides with // the prefix 'NOT' b alternative, and '(' b ')' in atoms, which puts @@ -21,9 +23,9 @@ // position, so a BETWEEN bound can end with a lambda whose body absorbs // 'AND' tokens: in `x BETWEEN y -> a AND b AND c` the first AND belongs // to the lambda body and the second is the separator. Which AND is the -// separator depends on the whole rest of the input, so the b-loop and the -// predicate decision become hybrid tables that escape to adaptivePredict -// on exactly these inputs (verified: both engines parse the corners below +// separator depends on the whole rest of the input, so the b-loop decision +// guards those states and defers to adaptivePredict on exactly these +// inputs (verified: both engines parse the corners below // identically, resolving maximal-munch like the runtime). DELETE the // lambda production and every decision in this grammar is statically // k=1 - function calls, IN lists, subscripts and LIKE..ESCAPE suffixes diff --git a/runtime/Rust/tests/gen/betweenexprparser.rs b/runtime/Rust/tests/gen/betweenexprparser.rs index 7fcae31ba5..3df27b7ea7 100644 --- a/runtime/Rust/tests/gen/betweenexprparser.rs +++ b/runtime/Rust/tests/gen/betweenexprparser.rs @@ -1180,15 +1180,15 @@ where // decision 2: LL(k), k=1, 3 states // decision 6: LL(k), k=1, 3 states // decision 8: LL(k), k=2, 13 states -// table 4 (decision 3): LL(k), k=1, 9 states, 1 adaptive escapes -// table 5 (decision 3): LL(k), k=1, 9 states, 1 adaptive escapes +// table 4 (decision 3): LL(k), k=1, 9 states, 1 guarded takes +// table 5 (decision 3): LL(k), k=1, 9 states, 1 guarded takes // table 6 (decision 3): LL(k), k=0, 1 states // table 7 (decision 7): LL(k), k=1, 9 states // table 8 (decision 7): LL(k), k=1, 10 states static ATN_SIMULATOR_MANAGER: LazyLock = LazyLock::new(|| ATNSimulatorManager::new(&_ATN)); static _ATN: LazyLock = LazyLock::new(|| ATNDeserializer::new(None).deserialize_compact(&_serializedATN)); -static _serializedATN: [&'static str; 19] = [ +static _serializedATN: [&'static str; 20] = [ "CAIijgEEAA4ABAIOAgQEDgQEBg4GBAgOCAIAAgACAAICAgICAgYCIhACAgICAgYCKhACAgICAgICAgIC", "AgICCgI6EAIUAhgCQBICAgQGBEYQBAIEAgQCBAIEAgQCBAIEBgRYEAQCBgIGAgYCBgIGAgYCBgIGAgYK", "Bm4QBhQGGAZ0EgYCCAIIAggCCAIIAggCCAIIAggGCIoBEAgCCAAEBAwKAAQIDBAABgIACg4CABASAgAU", @@ -1203,9 +1203,10 @@ static _serializedATN: [&'static str; 19] = [ "ODxEVmxwiAEOEhIAEjAABAIEBAICBAQEAAAAAAAAAAAAMDAwMDAwMDAwAQECAgIEBAQGBgYICAgKCg4M", "EBYOGhoQAAAAAAQGDAACBAAAAAAMDAwEBAIGBgQAAAAADAYMAAIEAAAAAAwMDBASAhQWBAAAAAAQGkgA", "BgAEAgICAgICAgIIAAACAAAAAAAAAAAAAAASEkhISEhISEhISEhIGBgCHh4EICAGAQEIAgIKBAQMBgYO", - "CAgQCg4SEBYUGhoWHBwYAAAAAAESMAAEBAECBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYG", - "BggICAoKDgwQFg4aGhAAAAAAARIwAAQEAQQEBAQEBAAAAAAAAAAAADAwMDAwMDAwMAEBAgICBAQEBgYG", - "CAgICgoODBAWDhoaEAAAAAABAgAEAAAAAAAAAAESMAAEBAQEBAQCBAQAAAAAAAAAAAAwMDAwMDAwMDAB", - "AQICAgQEBAYGBggICAoKDgwQFg4aGhAAAAAAARQ2AAQEBAQEBAIEBAQAAAAAAAAAAAAANjY2NjY2NjY2", - "NgEBAgICBAQEBgYGCAgICgoODBASDhQWEBoaEgAAAAAEBgQCBAgKDA4EBAYOEAw=" + "CAgQCg4SEBYUGhoWHBwYAAAAAAESMAAEBAUCBAQEBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYG", + "BggICAoKDgwQFg4aGhAAAgYCAkoWHB4mMDZOVFxkaoYBARIwAAQEBQQEBAQEBAAAAAAAAAAAADAwMDAw", + "MDAwMAEBAgICBAQEBgYGCAgICgoODBAWDhoaEAACBgICShYcHiYwNk5UXGRqhgEBAgAEAAAAAAAAAAES", + "MAAEBAQEBAQCBAQAAAAAAAAAAAAwMDAwMDAwMDABAQICAgQEBAYGBggICAoKDgwQFg4aGhAAAAAAARQ2", + "AAQEBAQEBAIEBAQAAAAAAAAAAAAANjY2NjY2NjY2NgEBAgICBAQEBgYGCAgICgoODBASDhQWEBoaEgAA", + "AAAEBgQCBAgKDA4EBAYOEAw=" ]; \ No newline at end of file diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 1d7bc97bf2..9bee1698f3 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -193,6 +193,16 @@ public static class Result { * fires (mirror + vetoes pass): would accept take (alt 1). */ public int takeRuleFires; public int guardedTakes; + /** Iterate/exit conflict states of a precedence-class build + * resolved to iterate (alt 1) by the guarded-iterate escape: + * vetoed by the enter/exit substitution only on foreign + * consumption, every foreign exit configuration rooted (see + * {@link #finalizeGuardedIterates}). */ + public int guardedIterates; + /** Iterate/exit conflicts resolved to iterate outright: the + * guarded-iterate escape found the foreign consumption + * unreachable on every real stack (empty danger set). */ + public int iterateAccepts; /** Conflict states resolved to min(U) by the uniform-widening * trust (every context entry has an assured min attestation). */ public int utrustResolutions; @@ -961,6 +971,8 @@ protected Result classifyPrecedence(DecisionState s) { } res.sawPrecPredicate |= attempt.sawPrecPredicate; res.usedWidening |= attempt.usedWidening; + res.guardedIterates += attempt.guardedIterates; + res.iterateAccepts += attempt.iterateAccepts; if (note.length() > 0) note.append(' '); note.append("p").append(c == 0 ? "<=" + cutoffs[0] : c < cutoffs.length ? "=" + (cutoffs[c-1]+1) + ".." + cutoffs[c] @@ -1248,6 +1260,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List stateDepth = new ArrayList(); // lookahead depth (BFS layer) List> ownRoots = new ArrayList>(); // postfix guard roots entering each state Map guardCandidates = new LinkedHashMap(); // take-vetoed conflict states -> their conflicting alternatives (null for budget escapes, never conflict-analyzed) + Map guardIterateCandidates = new LinkedHashMap(); // iterate/exit conflicts vetoed only on foreign consumption -> their conflicting alternatives this.currentDecisionRule = s.ruleIndex; Set start = new LinkedHashSet(); @@ -1424,6 +1437,13 @@ && hasPendingPrecReturn(c.context)) { } } } + if (hybridMode && exitForeign && !exitObligated && iterateReal) { + // vetoed only by foreign consumption of the exit + // lineage: a candidate for the guarded-iterate escape + // (resolved after construction, once guard roots have + // propagated) + guardIterateCandidates.put(d, conflicting); + } } // Optional-postfix take rule: the take/skip conflict of an @@ -1762,6 +1782,13 @@ else if (ls.roots != null) { guard = finalizeGuardedTakes(s, states, edges, acceptAlts, acceptMasks, ownRoots, guardCandidates, guardAlts, res); } + if (guard == null && hybridMode && currentPostfixShape == null + && !guardIterateCandidates.isEmpty() && !overflow && !res.sawPredicate) { + // iterate/exit conflicts vetoed only on foreign consumption get + // a second chance: the guarded-iterate escape + guard = finalizeGuardedIterates(s, states, edges, acceptAlts, acceptMasks, + ownRoots, guardIterateCandidates, guardAlts, res); + } if ("states".equals(System.getProperty("antlr.dfa.debug")) && String.valueOf(currentDecisionNumber).equals(System.getProperty("antlr.dfa.debug.decision"))) { @@ -1859,30 +1886,7 @@ protected GuardData finalizeGuardedTakes(DecisionState s, Map guardCandidates, List guardAlts, Result res) { - int n = states.size(); - // propagate guard roots through the edge graph to a fixpoint: - // through[s] = own[s] ∪ ∪_{p→s} through[p] - List> through = new ArrayList>(n); - Deque rq = new ArrayDeque(); - for (int i = 0; i < n; i++) { - Set own = ownRoots.get(i); - through.add(own != null ? new HashSet(own) : null); - if (own != null) rq.add(i); - } - while (!rq.isEmpty()) { - int p = rq.remove(); - Set rp = through.get(p); - for (int t : edges.get(p)) { - Set rt = through.get(t); - if (rt == null) { - through.set(t, new HashSet(rp)); - rq.add(t); - } - else if (rt.addAll(rp)) { - rq.add(t); - } - } - } + List> through = propagateGuardRoots(states, edges, ownRoots); Set G = new HashSet(); List guarded = new ArrayList(); @@ -1962,12 +1966,160 @@ else if (rt.addAll(rp)) { } return null; } + return computeGuardData(G); + } + + /** + * Guarded-iterate escape of a precedence-class build: an iterate/exit + * conflict the enter/exit substitution vetoed only on foreign + * consumption (the phantom consumer is not an enclosing invocation of + * this loop - the canonical shape is Trino's BETWEEN separator AND + * colliding with the booleanExpression loop's own AND). Exit + * configurations that stayed in the loop discipline (no + * FOREIGN_CONSUME_TAINT) are covered by the substitution's rejoin + * argument and need no guard; foreign ones are realizable only on + * runtime stacks whose epsilon-pop chase from the loop's exit reaches + * a guard root recorded when the foreign consumption was marked (the + * consumption position, plus the call sites of its non-loop context + * frames). The conflict resolves to iterate (alt 1) under the stack + * guard, or outright when no invoking state in the grammar can trip + * the guard: then the foreign consumption is epsilon-hidden from + * every follow region (it sits behind tokens no exit lineage can + * skip), so exit can never uniquely win on a real stack. + */ + protected GuardData finalizeGuardedIterates(DecisionState s, + List> states, + List> edges, + List acceptAlts, + List acceptMasks, + List> ownRoots, + Map guardIterateCandidates, + List guardAlts, + Result res) { + List> through = propagateGuardRoots(states, edges, ownRoots); - // danger[s]: an invoking state whose follow's epsilon-reachable - // region contains a guard root; pass[s]: the follow can reach its - // own rule's stop (the chase may keep popping). Exotic states with - // several rule transitions: danger = any follow, pass = all follows - // (conservative in both directions). + Set G = new HashSet(); + List guarded = new ArrayList(); + for (Map.Entry cand : guardIterateCandidates.entrySet()) { + int d = cand.getKey(); + if (acceptAlts.get(d) != StaticDFA.ESCAPE || acceptMasks.get(d) != 0) continue; + Set roots = through.get(d); + if (roots == null || roots.isEmpty()) continue; + boolean eligible = true; + boolean realTake = false; + for (ATNConfig c : states.get(d)) { + int taint = c.reachesIntoOuterContext; + if (c.alt == 1 + && (taint & (WIDENED_TAINT|FOREIGN_CONSUME_TAINT)) == 0) { + realTake = true; + } + if (c.alt != 2) continue; + // foreign consumption must be rooted: then the stack guard + // covers its realizability + if ((taint & FOREIGN_CONSUME_TAINT) != 0 + && (taint & ROOTED_TAINT) == 0) { + eligible = false; + break; + } + // a widening-born exit configuration is an analysis + // artifact unless it is rooted: then its consumption + // positions are guard-recorded + if ((taint & (WIDENED_TAINT|ROOTED_TAINT)) == WIDENED_TAINT) { + eligible = false; + break; + } + } + if (!eligible || !realTake) continue; + res.approxConflicts.remove(cand.getValue()); + res.contextSensitiveConflicts.remove(cand.getValue()); + res.exactAmbigConflicts.add(cand.getValue()); + acceptAlts.set(d, StaticDFA.GUARDED); + guardAlts.set(d, 1); + guarded.add(d); + G.addAll(roots); + res.guardedIterates++; + if ("guard".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("GUARD-ITERATE d=%d state=%d roots=%s%n", + s.decision, d, new TreeSet(roots)); + } + } + if (guarded.isEmpty()) return null; + + RuleStopState stop = atn.ruleToStopState[s.ruleIndex]; + if (stop != null) { + Set reach0 = reachEps(stop.stateNumber); + reach0.retainAll(G); + if (!reach0.isEmpty()) { + // a root is epsilon-reachable from the loop's exit + // continuation without popping any frame: the guard would + // defer on every stack - useless + for (int d : guarded) { + acceptAlts.set(d, StaticDFA.ESCAPE); + guardAlts.set(d, 0); + res.guardedIterates--; + } + return null; + } + } + + GuardData gd = computeGuardData(G); + if (gd.danger.length == 0) { + // no invocation's follow region contains a root: the foreign + // consumption is unreachable on every real stack past the + // loop's stop, so exit can never uniquely win - plain iterate + // accepts + for (int d : guarded) { + acceptAlts.set(d, 1); + guardAlts.set(d, 0); + res.guardedIterates--; + res.iterateAccepts++; + } + if ("guard".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("GUARD-ITERATE-STATIC d=%d states=%s%n", + s.decision, guarded); + } + return null; + } + return gd; + } + + /** Propagate guard roots through the edge graph to a fixpoint: + * through[s] = own[s] ∪ ∪_{p→s} through[p]. */ + private static List> propagateGuardRoots(List> states, + List> edges, + List> ownRoots) { + int n = states.size(); + List> through = new ArrayList>(n); + Deque rq = new ArrayDeque(); + for (int i = 0; i < n; i++) { + Set own = ownRoots.get(i); + through.add(own != null ? new HashSet(own) : null); + if (own != null) rq.add(i); + } + while (!rq.isEmpty()) { + int p = rq.remove(); + Set rp = through.get(p); + for (int t : edges.get(p)) { + Set rt = through.get(t); + if (rt == null) { + through.set(t, new HashSet(rp)); + rq.add(t); + } + else if (rt.addAll(rp)) { + rq.add(t); + } + } + } + return through; + } + + /** Danger/pass state sets of a guard root set (see {@link GuardData}): + * danger[s]: an invoking state whose follow's epsilon-reachable + * region contains a guard root; pass[s]: the follow can reach its + * own rule's stop (the chase may keep popping). Exotic states with + * several rule transitions: danger = any follow, pass = all follows + * (conservative in both directions). */ + private GuardData computeGuardData(Set G) { List danger = new ArrayList(); List pass = new ArrayList(); for (ATNState st : atn.states) { @@ -2028,12 +2180,27 @@ protected Set reachEps(int start) { * nothing - they are realizable through the decision's own take path. */ protected void collectGuardRoots(ATNConfig c, Set out) { - collectGuardRoots(c, c.context, out, + java.util.BitSet mirror = new java.util.BitSet(); + mirror.set(currentPostfixShape.blockEndState); + collectGuardRoots(c, out, mirror); + } + + /** + * {@link #collectGuardRoots(ATNConfig, Set)} with an explicit mirror + * set: deepest frames returning into {@code mirrorFollows} are + * realizable through the decision's own discipline (the postfix block + * end for the take guard, the operator-loop block for the iterate + * guard) and contribute no roots. + */ + protected void collectGuardRoots(ATNConfig c, Set out, + java.util.BitSet mirrorFollows) { + collectGuardRoots(c, c.context, out, mirrorFollows, java.util.Collections.newSetFromMap( new java.util.IdentityHashMap())); } private void collectGuardRoots(ATNConfig c, PredictionContext ctx, Set out, + java.util.BitSet mirrorFollows, Set visited) { if (ctx == null || ctx.isEmpty()) { out.add(c.state.stateNumber); @@ -2047,13 +2214,13 @@ private void collectGuardRoots(ATNConfig c, PredictionContext ctx, Set if (rs == PredictionContext.EMPTY_RETURN_STATE) { out.add(c.state.stateNumber); } - else if (rs != currentPostfixShape.blockEndState) { + else if (!mirrorFollows.get(rs)) { Integer site = siteByFollowState().get(rs); out.add(site != null ? site : rs); } } else { - collectGuardRoots(c, p, out, visited); + collectGuardRoots(c, p, out, mirrorFollows, visited); } } } @@ -2350,6 +2517,28 @@ else if (t instanceof WildcardTransition) { // operator loop: the phantom consumer is not an // enclosing invocation of this loop advanced.reachesIntoOuterContext |= FOREIGN_CONSUME_TAINT; + if (c.alt == 2 && currentPostfixShape == null + && (c.reachesIntoOuterContext & ROOTED_TAINT) == 0) { + // exit-lineage consumption outside the loop + // discipline: the advanced configuration is + // realizable only on runtime stacks whose + // epsilon-pop chase reaches the root position(s) + // this consumption passed through - record them + // for the guarded-iterate escape. The + // consumption position itself is a root: an exit + // that wins on a real stack must reach it through + // the popped frames, and the guard's danger set + // (invoking states whose follow region contains + // a root) covers exactly those stacks. Loop-block + // frames play the mirror role the block end + // plays for the postfix guard: consumption + // bottoming there is covered by the enter/exit + // substitution and needs no guard. + advanced.reachesIntoOuterContext |= ROOTED_TAINT; + if (succRoots == null) succRoots = new HashSet(); + succRoots.add(c.state.stateNumber); + collectGuardRoots(c, succRoots, precLoopStates); + } if ("full".equals(System.getProperty("antlr.dfa.debug")) && (c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) == 0) { System.err.printf("FOREIGN-MARK rule=%s state=%d alt=%d taint=%d ctx=%s label=%s%n", @@ -3252,6 +3441,15 @@ else if (r.dfa == null) { if (utrust > 0) { buf.append(String.format("utrust: %d conflict states resolved to min-alt%n", utrust)); } + int iterGuards = 0, iterAccepts = 0; + for (Result r : results) { + iterGuards += r.guardedIterates; + iterAccepts += r.iterateAccepts; + } + if (iterGuards > 0 || iterAccepts > 0) { + buf.append(String.format("iterate-guard: %d conflict states guarded, %d resolved outright%n", + iterGuards, iterAccepts)); + } int descentPlans = 0, descentMasks = 0; for (Result r : results) { if (r.descentMaskStates > 0) descentPlans++; From a18f283a8bea16378d239c37c276657894b7402f Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Wed, 29 Jul 2026 19:41:21 -0400 Subject: [PATCH 40/48] decision report: per-decision total table states on LR_PRECEDENCE lines Signed-off-by: Bo Lin --- tool/src/org/antlr/v4/analysis/DecisionClassifier.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 9bee1698f3..f96ff768d1 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -3472,6 +3472,7 @@ else if (r.dfa == null) { r.decisionState.decision, r.category)); buf.append(' ').append(r.precNote) .append(r.precDfa != null ? " [static]" : " [adaptive]") + .append(" states=").append(r.numDfaStates) .append(" fb=").append(fbString(r)).append('\n'); } continue; From 45361d272a305e470b92848849659cc070e3d837 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Wed, 29 Jul 2026 22:53:33 -0400 Subject: [PATCH 41/48] Frontier-iterate: resolve budget-frontier iterate/exit states of precedence loops by substitution attestation The enter/exit substitution of a precedence-class build resolves an iterate/exit conflict to iterate when the exit lineage's consumption stays in the loop discipline (no foreign frames), owes no pending tokens the iterate side does not also owe, and iterate viability is attested by a non-widened, non-foreign config. That certificate is a property of the exit LINEAGE, not of any collision - but it was only ever evaluated inside the conflict branch, so multi-alt states whose two sides never share an exact stack escaped at the budget frontier with both alts live. The canonical shape is Trino's valueExpression (d=254): after 'expr +|-', a reserved keyword-led operand (CAST, EXISTS, EXTRACT, GROUPING/LEFT/RIGHT, JSON_*, LISTAGG, NORMALIZE, TRIM - anything not in nonReserved, so no identifier pop-back creates a colliding $-rooted pair) leaves exactly two parallel configs, real iterate vs widened phantom exit, that never trigger hasSLLConflictTerminatingPrediction and die at the state cap. This change evaluates the same attestations at the budget frontier: a {1,2}-alt state of a substitutable simple-loop class build whose configs attest exactly ITERATE_REAL accepts iterate outright - the adaptive engine would answer iterate whenever it terminates (unique iterate, or an ambiguity resolved to the minimum alternative), so the resolution matches the runtime; on inputs where neither alt is viable the commit-vs-NoViableAlt recovery divergence is the accepted error-path class. The attestation evaluation is factored out of the conflict branch and shared verbatim. Effect (full-dialect sweep vs HEAD): - Trino d=254: 36e -> 0, all 6 classes clean k=2; d=318: 56e -> 32e - Bigquery d=330: 12e -> 0 (k=2); d=370: 44e -> 32e - Snowflake d=623: 24e -> 0 (k=2); d=687: 35e -> 31e - Databricks d=401: 149e -> 130e; Duckdb d=356: 57e -> 9e; Redshift d=333: 38e -> 8e - total escapes 11224 -> 11013 (-209); three decisions flip fully static (Trino d=254, Bigquery d=330, Snowflake d=623); no other decision touched anywhere Perf (Java twins): SELECT A + CAST(B AS INT) FROM T 11.2us static vs 13.7us adaptive; plain operator chains 11.7us vs 61.4us (5.2x). Verification: cargo 57/0 (witness battery), tool-testsuite 694/0, runtime-testsuite rust.** 707/707; 25-query targeted corpus of the cured shapes 25/0; tree diffs static-vs-adaptive: Trino 3208/2 and Bigquery 3208/3 (known :: error-path class), Duckdb 3208/0, Redshift 3208/0, ClickHouse 3208/4 (pre-existing ::/error-recovery class; its tables are provably untouched - zero frontier resolutions); Rust twins: Snowflake 1998/2 (pre-existing error-recovery count class), Databricks 1998/240 (>> error-recovery class, A/B-proven identical at HEAD - pre-existing, not from this change). Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 130 ++++++++++++------ 1 file changed, 87 insertions(+), 43 deletions(-) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index f96ff768d1..cbe59576f1 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -203,6 +203,10 @@ public static class Result { * guarded-iterate escape found the foreign consumption * unreachable on every real stack (empty danger set). */ public int iterateAccepts; + /** Budget-frontier iterate/exit states of a precedence-class build + * resolved to iterate by the substitution attestations, no conflict + * ever materializing (see buildDFA). */ + public int frontierIterates; /** Conflict states resolved to min(U) by the uniform-widening * trust (every context entry has an assured min attestation). */ public int utrustResolutions; @@ -973,6 +977,7 @@ protected Result classifyPrecedence(DecisionState s) { res.usedWidening |= attempt.usedWidening; res.guardedIterates += attempt.guardedIterates; res.iterateAccepts += attempt.iterateAccepts; + res.frontierIterates += attempt.frontierIterates; if (note.length() > 0) note.append(' '); note.append("p").append(c == 0 ? "<=" + cutoffs[0] : c < cutoffs.length ? "=" + (cutoffs[c-1]+1) + ".." + cutoffs[c] @@ -1374,45 +1379,10 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { if (precRuleIndex >= 0 && precClassSubstitutable && precSimpleLoop && conflicting.cardinality() == 2 && conflicting.get(1) && conflicting.get(2)) { - boolean exitForeign = false; - boolean exitObligated = false; - boolean iterateReal = false; - for (ATNConfig c : cs) { - if (c.alt == 2) { - if ((c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) != 0) { - exitForeign = true; - } - // Every phantom same-rule frame of the exit - // derivation must be free of token obligations - // outside the iteration-start region. An - // operand-start position owes the operand - - // exactly what the iterate reading owes too - // (both invoke the same operand next) - UNLESS - // its invocation returns into pending tokens of - // a compound alternative: the operand of a - // simple binary/unary operator returns to the - // alternative tail (nothing pending, benign), - // but a list element of expr (',' expr)* '>>' - // expr returns to a position owing ',' or '>>', - // which has no iterate-side counterpart - there - // the runtime can kill iterate with deeper - // lookahead and legitimately predict exit. - if (c.state.ruleIndex == precRuleIndex - && precPendingStates.get(c.state.stateNumber) - && hasPendingPrecReturn(c.context)) { - exitObligated = true; - } - if (hasObligatedReturn(c.context, - java.util.Collections.newSetFromMap( - new java.util.IdentityHashMap()))) { - exitObligated = true; - } - } - if (c.alt == 1 && (c.reachesIntoOuterContext - & (WIDENED_TAINT|FOREIGN_CONSUME_TAINT)) == 0) { - iterateReal = true; - } - } + int attest = iterateSubstitutionAttestations(cs); + boolean exitForeign = (attest & EXIT_FOREIGN) != 0; + boolean exitObligated = (attest & EXIT_OBLIGATED) != 0; + boolean iterateReal = (attest & ITERATE_REAL) != 0; if (!exitForeign && !exitObligated && iterateReal) { res.exactAmbigConflicts.add(conflicting); acceptAlts.set(d, 1); @@ -1690,6 +1660,25 @@ else if (abortInfAsOverflow) { s.decision, d, g.getRule(descentGroup.rule).name, descentGroup.alts); } } + else if (precRuleIndex >= 0 && precClassSubstitutable && precSimpleLoop + && alts.cardinality() == 2 && alts.get(1) && alts.get(2) + && iterateSubstitutionAttestations(cs) == ITERATE_REAL) { + // Budget-frontier iterate/exit state of a precedence loop: + // no conflict materialized before the cutoff, but the + // substitution attestations (a lineage property, independent + // of any collision) certify that exit can never become + // uniquely viable - its scanned tokens were all consumed by + // the loop discipline and it owes nothing iterate does not + // owe - so the adaptive engine answers iterate whenever it + // terminates: unique iterate, or an ambiguity resolved to + // the minimum alternative. Resolve without the scan. + res.frontierIterates++; + acceptAlts.set(d, 1); + if ("guard".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FRONTIER-ITERATE d=%d state=%d depth=%d%n", + s.decision, d, stateDepth.get(d)); + } + } else { acceptAlts.set(d, StaticDFA.ESCAPE); if (currentPostfixShape != null @@ -2834,6 +2823,60 @@ else if (!bottomFrameIs(p, endState, visited)) { return true; } + /** Iterate/exit substitution attestation bits (see + * {@link #iterateSubstitutionAttestations}). */ + protected static final int EXIT_FOREIGN = 1; + protected static final int EXIT_OBLIGATED = 2; + protected static final int ITERATE_REAL = 4; + + /** + * Iterate/exit substitution attestations of a state's configuration + * set (see the enter/exit substitution in buildDFA): {@link #EXIT_FOREIGN} + * when an exit configuration consumed in a foreign frame, + * {@link #EXIT_OBLIGATED} when an exit lineage owes pending tokens the + * iterate side does not also owe, {@link #ITERATE_REAL} when iterate + * viability is attested by a non-widened, non-foreign configuration. + * The substitution resolves to iterate when the result is exactly + * {@link #ITERATE_REAL}; {@code ITERATE_REAL|EXIT_FOREIGN} admits the + * state to the guarded-iterate escape. + */ + protected int iterateSubstitutionAttestations(Set cs) { + int attest = 0; + for (ATNConfig c : cs) { + if (c.alt == 2) { + if ((c.reachesIntoOuterContext & FOREIGN_CONSUME_TAINT) != 0) { + attest |= EXIT_FOREIGN; + } + // Every phantom same-rule frame of the exit derivation must be + // free of token obligations outside the iteration-start region. + // An operand-start position owes the operand - exactly what the + // iterate reading owes too (both invoke the same operand next) - + // UNLESS its invocation returns into pending tokens of a compound + // alternative: the operand of a simple binary/unary operator + // returns to the alternative tail (nothing pending, benign), but + // a list element of expr (',' expr)* '>>' expr returns to a + // position owing ',' or '>>', which has no iterate-side + // counterpart - there the runtime can kill iterate with deeper + // lookahead and legitimately predict exit. + if (c.state.ruleIndex == precRuleIndex + && precPendingStates.get(c.state.stateNumber) + && hasPendingPrecReturn(c.context)) { + attest |= EXIT_OBLIGATED; + } + if (hasObligatedReturn(c.context, + java.util.Collections.newSetFromMap( + new java.util.IdentityHashMap()))) { + attest |= EXIT_OBLIGATED; + } + } + if (c.alt == 1 && (c.reachesIntoOuterContext + & (WIDENED_TAINT|FOREIGN_CONSUME_TAINT)) == 0) { + attest |= ITERATE_REAL; + } + } + return attest; + } + private boolean hasPendingPrecReturn(PredictionContext ctx) { if (ctx == null || ctx.isEmpty()) return false; for (int i = 0; i < ctx.size(); i++) { @@ -3441,14 +3484,15 @@ else if (r.dfa == null) { if (utrust > 0) { buf.append(String.format("utrust: %d conflict states resolved to min-alt%n", utrust)); } - int iterGuards = 0, iterAccepts = 0; + int iterGuards = 0, iterAccepts = 0, iterFrontier = 0; for (Result r : results) { iterGuards += r.guardedIterates; iterAccepts += r.iterateAccepts; + iterFrontier += r.frontierIterates; } - if (iterGuards > 0 || iterAccepts > 0) { - buf.append(String.format("iterate-guard: %d conflict states guarded, %d resolved outright%n", - iterGuards, iterAccepts)); + if (iterGuards > 0 || iterAccepts > 0 || iterFrontier > 0) { + buf.append(String.format("iterate-guard: %d conflict states guarded, %d resolved outright, %d frontier states resolved%n", + iterGuards, iterAccepts, iterFrontier)); } int descentPlans = 0, descentMasks = 0; for (Result r : results) { From b7cf949a545748b172d347f0e20a6eec9839a734 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Thu, 30 Jul 2026 03:42:31 -0400 Subject: [PATCH 42/48] Phantom re-descent elimination: discharge exit obligations born from wildcard re-descents The iterate/exit substitution of precedence-loop decisions vetoed on any exit lineage owing pending tokens (a compound-alternative tail the iterate side does not owe). In expression-grammar postfix loops (the primaryExpression subscript/dereference family) every such obligation is an artifact of the wildcard closure: the exit side pops through the decision boundary, and the SLL caller-graph closure re-descends into a fresh expression juxtaposed after the completed primary - a continuation no real stack offers (real continuations consume a separator first, which the unmarked follow-position configurations cover). The phantom frames owe the tails of whatever compound alternatives the cascade invents (')', '(', '->', OVER, ','...), which the iterate side's own descent does not mirror, so the veto stood and 16 states per precedence class escaped. Track the birth of every exit-lineage (alt-2) context frame by 64-bit structural (value) key: frames born from a boundary-chased or widened/phantom-stacked lineage go to phantomFrameKeys, frames born clean to realFrameKeys; the obligation checks (hasObligatedReturn, hasPendingPrecReturn) skip a frame only when its value was born exclusively by wildcard lineages. Alt-2-scoping keeps clean iterate births of the same value from poisoning the classification, and the real-keys guard preserves the genuine obligation (the Send/list shape: an unchased in-rule list-element frame owing ',' or '>>' still vetoes). Value keys (with per-slot synthesis for merged contexts) survive the equal-value dedup that defeated identity-based tracking. Coverage (7-dialect sweep): Trino d=318 fully static (32e -> 0, both hybrid classes now k=2; escapes 878 -> 846), Bigquery d=370 (32e -> 0), Redshift d=409 (41e -> 1e), Snowflake d=687 (31e -> 1e), Databricks d=460 (191e -> 162e); Duckdb/ClickHouse unchanged. No decision regressed anywhere. Verification: cargo all suites, tool-testsuite 694/0, runtime-testsuite rust.** 707/707; tree diffs Trino 1680/2 + paren 1200/0 + err 10/0 + pred 318/0 (the 2 are the known '::' error-path class), Duckdb 2880/0, Redshift 2880/0, Databricks 2880/0. The Trino 172 and Bigquery 230 '>>' mismatches and the Snowflake 2 (q1532/q1581 error-count) reproduce identically with the pre-change tool - pre-existing divergences from the d=238/d=254 closure era on inputs where '>>' lexes as two GT tokens, flagged for separate investigation. Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 124 +++++++++++++++++- 1 file changed, 118 insertions(+), 6 deletions(-) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index cbe59576f1..081b530601 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -638,6 +638,28 @@ protected SharedDescentAnalyzer descentAnalyzer() { * analysis: consumption inside this rule is within the dangling-else * discipline and never marks {@link #ROOTED_TAINT}). */ protected int currentDecisionRule = -1; + /** Identity set of context frames born from a phantom re-descent: a + * rule invocation whose invoking configuration had popped through the + * wildcard context ({@link #BOUNDARY_TAINT}) or whose stack already + * contained a widened joint or a phantom-born frame. Such frames + * hypothesize a fresh descent juxtaposed after the completed rule - + * a continuation no real stack offers (a completed expression is + * always followed by a separator, which the unmarked follow-position + * configurations consume first) - so token obligations attributed to + * them (see {@link #hasObligatedReturn}) are dead and discharged. + * Tracked by 64-bit structural (value) key, not identity: equal-value + * twins of a phantom-born node arise through independent lineages + * and configuration dedup keeps whichever arrived first. + * {@link #realFrameKeys} guards the poisoning direction: a value + * also born by a clean (non-phantom) lineage is never skipped. + * Both per construction attempt. */ + protected Set phantomFrameKeys; + /** Structural keys of frames born by clean lineages (no boundary + * chase, no widened or phantom ancestor); see + * {@link #phantomFrameKeys}. */ + protected Set realFrameKeys; + /** Memo for {@link #frameKey} (contexts share structure). */ + protected Map frameKeyCache; /** Lazily built: a rule call's follow state -> the call-site state * owning the {@link RuleTransition} (the invoking state a real parse * stack carries for that call). */ @@ -1255,6 +1277,9 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { this.faithCache = new java.util.IdentityHashMap(); this.widenedJoints = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()); + this.phantomFrameKeys = new HashSet(); + this.realFrameKeys = new HashSet(); + this.frameKeyCache = new java.util.IdentityHashMap(); Map stateIds = new HashMap(); List> states = new ArrayList>(); List> edges = new ArrayList>(); @@ -2675,6 +2700,19 @@ else if (contextDepth(config.context) >= currentDepthBound newCtx = SingletonPredictionContext.create(config.context, followStateNumber); } ATNConfig callee = new ATNConfig(config, rt.target, newCtx); + if (config.alt == 2 && !newCtx.isEmpty()) { + // phantom re-descent birth (see phantomFrameKeys): an + // invocation from a wildcard-born lineage hypothesizes a + // juxtaposed descent no real stack offers. Alt-2-scoped: + // exit-lineage chains only ever carry exit-born frame + // values, so clean iterate births of the same value must + // not poison the classification. + boolean phantomBirth = + (config.reachesIntoOuterContext & BOUNDARY_TAINT) != 0 + || ctxContainsWildcard(config.context); + (phantomBirth ? phantomFrameKeys : realFrameKeys) + .add(frameKey(newCtx)); + } if (widened) { res.usedWidening = true; callee.reachesIntoOuterContext |= WIDENED_TAINT; @@ -2857,7 +2895,10 @@ protected int iterateSubstitutionAttestations(Set cs) { // a list element of expr (',' expr)* '>>' expr returns to a // position owing ',' or '>>', which has no iterate-side // counterpart - there the runtime can kill iterate with deeper - // lookahead and legitimately predict exit. + // lookahead and legitimately predict exit. Frames born from a + // phantom re-descent ({@link #phantomFrameKeys}) are skipped: + // they hypothesize a juxtaposed fresh descent no real stack + // offers, so their obligations are dead. if (c.state.ruleIndex == precRuleIndex && precPendingStates.get(c.state.stateNumber) && hasPendingPrecReturn(c.context)) { @@ -2877,11 +2918,68 @@ && hasPendingPrecReturn(c.context)) { return attest; } + /** Does the context chain pass through a wildcard artifact - a + * widened joint ({@link #widenedJoints}) or a phantom-born frame + * ({@link #phantomFrameKeys})? A frame pushed above such a node is a + * post-cut hypothesis. Keys poisoned by a clean twin + * ({@link #realFrameKeys}) still count as wildcard here: the + * birth-side marking errs toward phantom, and the skip sites apply + * the clean-twin guard. + */ + private boolean ctxContainsWildcard(PredictionContext ctx) { + if (ctx == null || ctx.isEmpty()) return false; + if (widenedJoints.contains(ctx)) return true; + for (int i = 0; i < ctx.size(); i++) { + if (phantomFrameKeys.contains( + slotKey(frameKey(ctx.getParent(i)), ctx.getReturnState(i)))) { + return true; + } + if (ctxContainsWildcard(ctx.getParent(i))) return true; + } + return false; + } + + /** Structural (value) key of a context frame: equal-value twins of a + * node share a key regardless of which object configuration dedup + * kept. 64-bit to keep collisions negligible. */ + private long frameKey(PredictionContext ctx) { + if (ctx == null || ctx.isEmpty()) return 0L; + Long cached = frameKeyCache.get(ctx); + if (cached != null) return cached; + long h = 0x9e3779b97f4a7c15L; + for (int i = 0; i < ctx.size(); i++) { + h = mix(h, frameKey(ctx.getParent(i)), ctx.getReturnState(i)); + } + h = avalanche(h); + frameKeyCache.put(ctx, h); + return h; + } + + /** The frame key of a single-slot context of the given parent key + * and return state - equals {@link #frameKey} of a singleton of the + * same shape, so array slots (whose merged node never went through a + * birth) can be tested against the birth classifications. */ + private long slotKey(long parentKey, int returnState) { + return avalanche(mix(0x9e3779b97f4a7c15L, parentKey, returnState)); + } + + private static long mix(long h, long parentKey, int returnState) { + return h * 0x100000001b3L ^ (parentKey + 31L * (returnState + 1)); + } + + private static long avalanche(long h) { + h ^= h >>> 29; + h *= 0xbf58476d1ce4e5b9L; + h ^= h >>> 32; + return h; + } + private boolean hasPendingPrecReturn(PredictionContext ctx) { if (ctx == null || ctx.isEmpty()) return false; for (int i = 0; i < ctx.size(); i++) { int rs = ctx.getReturnState(i); - if (rs != PredictionContext.EMPTY_RETURN_STATE) { + if (rs != PredictionContext.EMPTY_RETURN_STATE + && !phantomSlot(frameKey(ctx.getParent(i)), rs)) { ATNState st = atn.states.get(rs); if (st.ruleIndex == precRuleIndex && precPendingStates.get(rs)) { @@ -2892,11 +2990,23 @@ private boolean hasPendingPrecReturn(PredictionContext ctx) { return false; } + /** Phantom-born-frame test for the obligation checks: the frame's + * value was only ever born from a wildcard lineage (a value also + * born cleanly by the exit lineage - {@link #realFrameKeys} - is + * never phantom). */ + private boolean phantomSlot(long parentKey, int returnState) { + long k = slotKey(parentKey, returnState); + return phantomFrameKeys.contains(k) && !realFrameKeys.contains(k); + } + /** * Does the context chain contain a same-rule return state with a - * token obligation outside the iteration-start region - a phantom - * frame of the precedence rule that cannot be discharged by iterating - * (see {@link #precPendingStates})? + * token obligation outside the iteration-start region - a frame of + * the precedence rule that cannot be discharged by iterating (see + * {@link #precPendingStates})? Phantom-born frames + * ({@link #phantomContexts}) are skipped: they model a juxtaposed + * re-descent that no real stack can realize, so their obligations + * cannot make the exit side uniquely viable. */ private boolean hasObligatedReturn(PredictionContext ctx, Set visited) { if (ctx == null || ctx.isEmpty() || !visited.add(ctx)) return false; @@ -2904,7 +3014,9 @@ private boolean hasObligatedReturn(PredictionContext ctx, Set int rs = ctx.getReturnState(i); if (rs != PredictionContext.EMPTY_RETURN_STATE) { ATNState st = atn.states.get(rs); - if (st.ruleIndex == precRuleIndex + boolean phantom = phantomSlot(frameKey(ctx.getParent(i)), rs); + if (!phantom + && st.ruleIndex == precRuleIndex && precPendingStates.get(rs)) { return true; } From 591436be37d1f443b1f9ad2078be2c98e9e95fb8 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 31 Jul 2026 00:40:12 -0400 Subject: [PATCH 43/48] staticDFACanDefer: account for guarded-take states (fix silent wrong-skip regression) e99725695 made all remaining escapes of optional-postfix decisions resolve to guarded takes, driving their escape count to zero. The tableCanDefer gate (339d09562: emit the adaptivePredict fallback only where it can fire) only consulted hasEscapes()/hasMasks(), so the generated Rust parser lost its adaptive fallback for these all-guarded decisions. But a guarded-take state still defers at runtime: when the real-stack epsilon-pop chase trips a guardDanger state, dfa_predict returns INVALID_ALT - which, with no fallback arm, silently fell into the skip arm of the generated match. Symptom (Snowflake): functionCallTail d=691 guard-defer on 'f(x) OVER (PARTITION BY k)' was misread as skip, OVER got consumed as the select-item alias (over_alias=OVER), and the window spec then failed at top level - static/adaptive PARSE-DIVERGENCE on the differential corpus. StaticDFA.hasGuards() already documents exactly this deferral; it just was never consulted. The fallback wrapper is now emitted for any table with guarded states. tableCanDefer is consumed only by Rust.stg, so no other target is affected. Verification: Snowflake differential corpus (2893 files, static vs adaptive) 0 divergences; DFA-TRACE confirms guard-defer d=691 now routes to adaptivePredict. Signed-off-by: Bo Lin --- tool/src/org/antlr/v4/codegen/ParserFactory.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index 4c5c87d3d7..84043dab46 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -291,7 +291,9 @@ protected boolean staticDFACanDefer(int decision) { } org.antlr.v4.analysis.StaticDFA dfa = g.staticDecisionDFAs != null ? g.staticDecisionDFAs.get(decision) : null; - return dfa != null && (dfa.hasEscapes() || dfa.hasMasks()); + // guarded-take states defer too: the runtime guard punts to + // adaptivePredict when the parse stack trips the guard's danger set + return dfa != null && (dfa.hasEscapes() || dfa.hasMasks() || dfa.hasGuards()); } /** Does the decision's emitted table contain a mask-accept covered From 0f0ca2843b1c58de8cb8521469431e29474a6c6e Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 31 Jul 2026 01:19:29 -0400 Subject: [PATCH 44/48] utrust: never resolve start-state (depth 0) conflicts to min-alt 8ff68e904's uniform-widening trust resolved Snowflake property d=387's start-state conflict to alt 1, collapsing the table to a single k=0 accept. A depth-0 accept answers the decision without consuming a single token, but the runtime never reports a conflict before consuming input either - alt-viability pruning comes first, so min(U) is the runtime's answer only for inputs that actually reach the conflict. The depth-0 collision is a widening artifact of the shared closure: both alts of property: propertyKey EQ LPAREN property* RPAREN #nestedProperty | propertyKey EQ propertyValue #defaultProperty meet on (state, $) inside the common propertyKey/identifier prefix before any input disambiguates them, and utrust's per-entry assured-min attestations (ctx=$ shadows, faithful under the identity-tracked joints) covered every entry. Result: HANDLER = 'MyClass.myMethod' in CREATE FUNCTION ... LANGUAGE JAVA statically entered nestedProperty and failed expecting '(', where adaptive picks defaultProperty - a static/adaptive PARSE-DIVERGENCE. Depth >= 1 resolutions are unaffected: there the walker consumes input before accepting, so only inputs that genuinely reach the conflict get the min-alt answer (statement d=45/d=90 keep their utrust tables). Start-state conflicts now fall through to the escape/adaptive path, the pre-8ff68e904 behavior; with the doomed-attempt pruning of 280597ba6 d=387's exact attempt completes outright (LLK, k=4). Verification: Snowflake differential corpus 2894 files, 0 divergences (incl. the cov3 CREATE FUNCTION HANDLER witness); Rust unit tests; tool-testsuite 694/694; runtime-testsuite rust.** 707/707. Signed-off-by: Bo Lin --- .../org/antlr/v4/analysis/DecisionClassifier.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 081b530601..40fc86c8d3 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -1551,7 +1551,19 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { acceptAlts.set(d, conflicting.nextSetBit(0)); } else { - int um = utrustMinAlt(cs, conflicting, anyBoundary, allBoundary); + // Never resolve a start-state (depth 0) conflict: a min-alt + // accept there answers the decision without consuming a single + // token, but the runtime never reports a conflict before + // consuming input either - alt-viability pruning comes first, + // so min(U) is the runtime's answer only for inputs that + // actually reach the conflict. The depth-0 collision is a + // widening artifact of the shared closure (both alts' configs + // meet on (state, $) inside the common prefix before any input + // disambiguates them; Snowflake property d=387 resolved + // 'K = ' to nestedProperty, which then failed + // expecting '('). Leave it to escape to adaptivePredict. + int um = stateDepth.get(d) > 0 + ? utrustMinAlt(cs, conflicting, anyBoundary, allBoundary) : 0; if (um > 0) { // uniform-widening trust: min(U) is the runtime's // answer on every real stack (see utrustMinAlt) From 8ef88ae08e97533c19c96acddd1ec8fd609668cf Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 31 Jul 2026 02:16:20 -0400 Subject: [PATCH 45/48] Mask protocol: decisions with >64 alternatives escape instead of overflowing 40b145d8e's v6 table format funnels every walker result through u64 alternative masks (1<<(alt-1) per alt), but nothing stopped the tool from emitting tables for decisions with more than 64 alternatives. Redshift's 80-alt statement decision statically accepted alt 68 for 'CREATE LIBRARY foo' and the walker's accept shift overflowed (panic in debug builds; a silently wrong bit in release). Mask accepts were worse: altBits() computes 1L<<(a-1) in Java, which wraps mod 64, so an over-64 group would have produced a silently corrupted mask with no panic at all. Same hazard in the descent-codegen adaptive-fallback arms (wrapping_shl of an adaptive alt). Rather than demoting such decisions to fully adaptive (which cost Snowflake statement d=310 its 97%-coverage hybrid table), the fix is per-state: over-64 accepts become escapes in hybrid mode, deferring exactly those inputs to adaptivePredict; in a full-table attempt they fail the construction, which then retries in hybrid mode. Mask acceptance (prefix-factor and shared-descent) is skipped for groups reaching past alt 64, and descent codegen falls back to the plain DFAAltBlock for >64-alt decisions. The Rust walker also defers on over-64 accepts/fallbacks as stale-table defense (returning 0 instead of panicking). Verified: Redshift differential corpus 2894 files 0 divergences ('CREATE LIBRARY foo' parses; statement d=114 keeps a hybrid table, cover=84%); Snowflake d=310 stays hybrid (escapes 19->30); Rust unit tests; tool-testsuite 694/694; runtime-testsuite rust.** 707/707. Signed-off-by: Bo Lin --- runtime/Rust/src/parser.rs | 12 +++++++ .../antlr/v4/analysis/DecisionClassifier.java | 31 +++++++++++++++---- .../org/antlr/v4/codegen/ParserFactory.java | 4 +++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 9a1edcfc2c..6272e5e726 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -859,6 +859,13 @@ where return Ok(mask); } if alt > 0 { + if alt > 64 { + // the mask encoding cannot represent alternatives + // above 64: the tool never emits tables for such + // decisions, but a stale table defers rather than + // overflowing the shift + return Ok(0); + } return Ok(1u64 << (alt - 1)); } let t = self.input.la(i); @@ -874,6 +881,11 @@ where // mismatch point - mirroring adaptive_predict's // finished-decision-entry-rule recovery. if let Some(alt) = dfa.fallback(s) { + if alt > 64 { + // see the accept path above: stale-table + // defense, never emitted by the tool + return Ok(0); + } return Ok(1u64 << (alt - 1)); } let start = self.input.lt(1).map(|t| OwningToken::from(t as &dyn Token)); diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 40fc86c8d3..d0fd290261 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -700,7 +700,6 @@ public Result classify(DecisionState s) { res.k = 1; return res; } - // alt-mask dry run: compute the prefix-factor plan up front; the // construction attempts count the states it would resolve. this.currentFactorPlan = factorAnalyzer.analyze(s); @@ -810,7 +809,6 @@ protected boolean isPrecedenceLoopDecision(DecisionState s) { protected Result classifyPrecedence(DecisionState s) { Result res = new Result(s); res.category = Category.LR_PRECEDENCE; - // distinct guard constants of this rule's operator alternatives TreeSet cutSet = new TreeSet(); for (ATNState st : atn.states) { @@ -1591,7 +1589,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { // prefix-factor group, in which case it accepts // with the group's alternative mask (the parser // resolves the choice at the tail decision) - if (factorGroup != null) { + if (factorGroup != null && factorGroup.alts.length() <= 64) { res.factorEscapesCured++; res.approxConflicts.remove(conflicting); res.contextSensitiveConflicts.remove(conflicting); @@ -1605,7 +1603,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { descentGroup = pickDescentGroup( currentDescentPlan.groupsCovering(alts), configs, s); } - if (descentGroup != null) { + if (descentGroup != null && alts.length() <= 64) { res.descentMaskStates++; res.approxConflicts.remove(conflicting); res.contextSensitiveConflicts.remove(conflicting); @@ -1678,7 +1676,7 @@ else if (abortInfAsOverflow) { // first rank (bounded by the token alphabet) must not starve // its own siblings, or single-token predictions - the // dynamic majority - escape on sheer decision fanout. - if (factorGroup != null) { + if (factorGroup != null && factorGroup.alts.length() <= 64) { res.factorEscapesCured++; acceptMasks.set(d, altBits(factorGroup.alts)); } @@ -1689,7 +1687,7 @@ else if (abortInfAsOverflow) { descentGroup = pickDescentGroup( currentDescentPlan.groupsCovering(alts), configs, s); } - if (descentGroup != null) { + if (descentGroup != null && alts.length() <= 64) { res.descentMaskStates++; acceptMasks.set(d, altBits(alts)); if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { @@ -1798,6 +1796,27 @@ else if (ls.roots != null) { boolean cyclic = isCyclic(edges); if (!cyclic) res.k = longestPath(edges); + // The mask protocol encodes alternatives as bits of a u64 + // (1<<(alt-1) per alt): alternatives above 64 are unrepresentable + // (Redshift's 80-alt statement decision - CREATE LIBRARY is alt + // 68 - overflowed the walker's accept shift). Over-64 accepts + // become escapes in hybrid mode, deferring exactly those inputs + // to adaptivePredict; in a full-table attempt they fail the + // construction, which then retries in hybrid mode. Mask accepts + // are excluded at their sites (hybrid mode only); fallbacks are + // error-path hints and are simply dropped. + for (int d = 0; d < acceptAlts.size(); d++) { + if (acceptAlts.get(d) > 64) { + if (!hybridMode) { + res.numDfaStates = states.size(); + res.category = Category.CONTEXT_SENSITIVE; + return false; + } + acceptAlts.set(d, StaticDFA.ESCAPE); + } + if (fallbackAlts.get(d) > 64) fallbackAlts.set(d, 0); + } + // Take-vetoed conflict states get a second chance: the // guarded-take escape (see finalizeGuardedTakes). List guardAlts = new ArrayList( diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index 84043dab46..394e1cc0dd 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -210,6 +210,10 @@ else if ( hasStaticDFA(decision) ) { g.staticDescentPlans != null ? g.staticDescentPlans.get(decision) : null; org.antlr.v4.codegen.model.DescentAltBlock descentBlock = descentPlan != null && gen.getTarget().supportsFactoredAltMask() + // the descent arms dispatch on u64 alt masks: decisions + // with more than 64 alternatives use the plain block (the + // over-64 accepts of its table escape anyway) + && ((DecisionState)blkAST.atnState).getNumberOfTransitions() <= 64 && org.antlr.v4.analysis.SharedDescentAnalyzer.hasDescentMask(g, decision) ? buildDescentAltBlock(dfaBlock, descentPlan) : null; if ("descent".equals(System.getProperty("antlr.dfa.debug"))) { From fd4e77a09138e57253746d992ccd4675f08e3094 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 31 Jul 2026 11:53:02 -0400 Subject: [PATCH 46/48] Phantom re-descent birth: only juxtaposed (separator-free) lineages discharge obligations 37c57a405's birth predicate marked every boundary-chased or wildcard-context re-descent frame phantom and discharged its token obligations. The premise - phantom frames hypothesize a juxtaposed fresh descent no real stack offers - does not hold for frames born after the lineage consumed a separator: those model real continuation shapes, and cov4 found one. Snowflake primaryExpression's base alternatives include the self-referential PRIOR base_=primaryExpression DOT derefName=columnNameComponent For 'CONNECT BY PRIOR B.ID = B.PARENT_ID' the wildcard cascade re-descends into primaryExpression at that alternative after consuming PRIOR, hypothesizing a frame that owes the alternative's DOT after the completed base operand. The real stack of this input contains exactly that frame: discharging its obligation let the iterate/exit substitution resolve ITERATE after 'PRIOR B', so the inner primary swallowed '.ID' and the outer alternative's DOT then failed at '=' (mismatched input '=' expecting {'::', '[', '.', ':'}). Adaptive exits the inner loop. The new CONSUMED_TAINT bit (32, max-merge-safe) marks any token consumption by a boundary-popped lineage, loop-disciplined or foreign. Only separator-free (truly juxtaposed) births remain phantom. In practice the discharged obligations were all born past a separator, so the escape wins of 37c57a405 revert (Snowflake d=687 1e->31e, Trino d=318 0->32e, Bigquery d=370 0->32e, Redshift d=409 1e->41e) - the premise behind them was unsound; what remains is the pre-37c57a405 behavior for those decisions, with the discharge machinery kept for genuinely juxtaposed births. Verification: Snowflake differential corpus 2895 files 0 divergences (cov4 and the minimized 'SELECT * FROM t AS B CONNECT BY PRIOR B.ID = B.PARENT_ID' included); Rust unit tests; tool-testsuite 694/694; runtime-testsuite rust.** 707/707. Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index d0fd290261..59d9c00657 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -290,6 +290,22 @@ public Result(DecisionState decisionState) { */ protected static final int FOREIGN_CONSUME_TAINT = 8; + /** + * Taint for configurations that consumed a token after popping + * through the decision-entry wildcard context (any consumption by a + * {@link #BOUNDARY_TAINT boundary-popped} lineage, whether inside the + * loop discipline or foreign to it). Distinguishes genuine separated + * continuations from juxtaposition phantoms for the phantom re-descent + * birth classification ({@link #phantomFrameKeys}): a frame invoked by + * a lineage that already consumed a separator models a real + * continuation shape (e.g. the {@code PRIOR} of the self-referential + * base alternative, or the {@code =} of a boolean equality), so its + * token obligations must not be discharged. Assigned above every other + * taint bit so configuration merging (which takes the numeric max) + * never loses it. + */ + protected static final int CONSUMED_TAINT = 32; + /** * Taint for rooted configurations of the optional-postfix * guard analysis: a skip-lineage (alt 2) configuration that consumed a @@ -2551,6 +2567,11 @@ else if (t instanceof WildcardTransition) { ATNConfig advanced = new ATNConfig(c, moveTargets.get(m)); if (precRuleIndex >= 0 && (c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0) { + // any consumption by a boundary-popped lineage marks the + // descent separated (CONSUMED_TAINT): re-descent frames born + // past this point model real separator-led continuations, + // not juxtaposition phantoms (see phantomFrameKeys) + advanced.reachesIntoOuterContext |= CONSUMED_TAINT; if (isLoopConsumption(c)) { // loop-block consumption by a boundary-popped // config: the phantom consumer is an enclosing @@ -2733,14 +2754,22 @@ else if (contextDepth(config.context) >= currentDepthBound ATNConfig callee = new ATNConfig(config, rt.target, newCtx); if (config.alt == 2 && !newCtx.isEmpty()) { // phantom re-descent birth (see phantomFrameKeys): an - // invocation from a wildcard-born lineage hypothesizes a - // juxtaposed descent no real stack offers. Alt-2-scoped: - // exit-lineage chains only ever carry exit-born frame - // values, so clean iterate births of the same value must - // not poison the classification. + // invocation from a wildcard-born lineage that consumed + // NOTHING since the pop hypothesizes a juxtaposed descent + // no real stack offers. A lineage that already consumed a + // separator (CONSUMED_TAINT: the PRIOR of the self- + // referential base alternative, the = of a boolean + // equality, an argument-list , or () models a real + // continuation shape - cov4's CONNECT BY PRIOR B.ID = ... + // is parsed through exactly such a frame - so its + // obligations stand. Alt-2-scoped: exit-lineage chains + // only ever carry exit-born frame values, so clean + // iterate births of the same value must not poison the + // classification. boolean phantomBirth = - (config.reachesIntoOuterContext & BOUNDARY_TAINT) != 0 - || ctxContainsWildcard(config.context); + (config.reachesIntoOuterContext & CONSUMED_TAINT) == 0 + && ((config.reachesIntoOuterContext & BOUNDARY_TAINT) != 0 + || ctxContainsWildcard(config.context)); (phantomBirth ? phantomFrameKeys : realFrameKeys) .add(frameKey(newCtx)); } From d99617802bbf13e786162363557c415572ae4130 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 31 Jul 2026 13:36:27 -0400 Subject: [PATCH 47/48] Guarded-obligation iterate: stack-guarded discharge of phantom exit obligations 37c57a405 discharged the exit lineage's pending-token obligations of phantom-born frames outright. The premise is unsound in both directions, and 399ed908d's separator test did not save it: the caller shape that makes the exit uniquely viable (Snowflake's self-referential base alternative 'PRIOR base_=primaryExpression DOT derefName', hit by 'CONNECT BY PRIOR B.ID = ...') may never appear in the conflict's context set at all - the phantom cascade's re-descent does not have to reach it for a real stack to sit on it. No static analysis of the conflict can decide this; only the runtime stack can. The discharge is now a stack guard. Iterate/exit states vetoed only by phantom-born obligations (conflict substitutions and budget frontier alike) accept as GUARDED iterate; the guard's roots are every pending position of the precedence rule's BASE alternatives - the operator alternatives' own pending positions are owed by the iterate reading too and are excluded (partitioned by local control-flow reachability from the precpred heads, cut at the LoopEndState: the transformed rule wraps from there back into the base block). At runtime the guard chase defers to adaptivePredict exactly when an invoking frame on the real stack returns into such a position - 'PRIOR B' (base_ returning into the alternative's pending DOT) defers, while 'f(B.ID)' (an argument returning into a different rule's separators) and standalone 'B.ID' (enclosing loop invocation, not pending) take the static iterate. The base_ operand frames of the loop's own dereference alternative are operator positions, so chained dereferences stay static as well. Real-born obligations still veto outright (the Send/list witness is preserved), and both useless-guard eliminations apply (empty danger reverts to a plain iterate accept; a root reachable from the loop exit reverts to escape). Escape wins of 37c57a405 are restored, now guarded: Snowflake d=687 31e -> 1e (30 obligation-guarded), Trino d=318 32e -> 0 (32), Bigquery d=370 32e -> 0 (32), Redshift d=409 41e -> 1e (40), Databricks 29. Verification: Snowflake differential corpus 2895 files 0 divergences (cov4 defers correctly, DFA-TRACE shows guard-defer on the PRIOR stack and guard-take on the standalone dereference in the same query); Rust unit tests; tool-testsuite 694/694; runtime-testsuite rust.** 707/707. Signed-off-by: Bo Lin --- .../antlr/v4/analysis/DecisionClassifier.java | 298 +++++++++++++----- 1 file changed, 214 insertions(+), 84 deletions(-) diff --git a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java index 59d9c00657..20cc2c7118 100644 --- a/tool/src/org/antlr/v4/analysis/DecisionClassifier.java +++ b/tool/src/org/antlr/v4/analysis/DecisionClassifier.java @@ -199,6 +199,14 @@ public static class Result { * consumption, every foreign exit configuration rooted (see * {@link #finalizeGuardedIterates}). */ public int guardedIterates; + /** Iterate/exit states accepted as GUARDED iterate on obligations + * of phantom-born frames alone (the runtime stack guard defers + * when such a frame is on the real stack). */ + public int guardedObligations; + /** Phantom-obligation states resolved to iterate outright: the + * discharged frames are unreachable on every real stack (empty + * danger set). */ + public int obligationAccepts; /** Iterate/exit conflicts resolved to iterate outright: the * guarded-iterate escape found the foreign consumption * unreachable on every real stack (empty danger set). */ @@ -290,21 +298,6 @@ public Result(DecisionState decisionState) { */ protected static final int FOREIGN_CONSUME_TAINT = 8; - /** - * Taint for configurations that consumed a token after popping - * through the decision-entry wildcard context (any consumption by a - * {@link #BOUNDARY_TAINT boundary-popped} lineage, whether inside the - * loop discipline or foreign to it). Distinguishes genuine separated - * continuations from juxtaposition phantoms for the phantom re-descent - * birth classification ({@link #phantomFrameKeys}): a frame invoked by - * a lineage that already consumed a separator models a real - * continuation shape (e.g. the {@code PRIOR} of the self-referential - * base alternative, or the {@code =} of a boolean equality), so its - * token obligations must not be discharged. Assigned above every other - * taint bit so configuration merging (which takes the numeric max) - * never loses it. - */ - protected static final int CONSUMED_TAINT = 32; /** * Taint for rooted configurations of the optional-postfix @@ -505,6 +498,10 @@ public Result(DecisionState decisionState) { * too - and is benign. */ protected java.util.BitSet precPendingStates; + /** Pending positions of the precedence rule's base (non-operator) + * alternatives; guard roots of the guarded-obligation iterate + * accept. See classifyPrecedence. */ + protected java.util.BitSet precBasePendingStates; /** * True while building any precedence class in which the enter/exit @@ -935,6 +932,46 @@ protected Result classifyPrecedence(DecisionState s) { } } + // Pending positions of the rule's BASE alternatives (the operator + // alternatives' own pending positions - the dereference DOT family + // - are owed by the iterate reading too and are excluded): the + // guard roots of the guarded-obligation iterate accept (see + // finalizeGuardedIterates). A caller invocation from such a + // position owes tokens the loop cannot provide - exactly the + // substitution's blind spot (the PRIOR base_ . derefName + // alternative's DOT, which the phantom cascade's re-descent may + // never reach, yet a real CONNECT BY stack sits on). + java.util.BitSet loopAltStates = new java.util.BitSet(); + Deque altWork0 = new ArrayDeque(); + for (ATNState st : atn.states) { + if (st == null || st.ruleIndex != s.ruleIndex) continue; + for (int i = 0; i < st.getNumberOfTransitions(); i++) { + Transition t = st.transition(i); + if (t instanceof PrecedencePredicateTransition) altWork0.add(t.target); + } + } + while (!altWork0.isEmpty()) { + ATNState x = altWork0.remove(); + if (x.ruleIndex != s.ruleIndex || loopAltStates.get(x.stateNumber)) continue; + loopAltStates.set(x.stateNumber); + // the loop's local flow ends at the loop end: past it the + // transformed rule wraps back to the base-alternative block + // (LoopEndState -> block end), which is not loop machinery + if (x instanceof LoopEndState || x instanceof RuleStopState) continue; + for (int i = 0; i < x.getNumberOfTransitions(); i++) { + Transition t = x.transition(i); + // stay in the alternative's local control flow: an + // invocation returns to its follow state; the callee's + // body (notably the rule's own start via an operand + // call) is not part of the loop alternative + altWork0.add(t instanceof RuleTransition + ? ((RuleTransition)t).followState : t.target); + } + } + this.precBasePendingStates = new java.util.BitSet(); + precBasePendingStates.or(precPendingStates); + precBasePendingStates.andNot(loopAltStates); + // Simplicity of the guarded alternatives (see precSimpleLoop): // walk each precedence-guarded alternative's continuation. this.precSimpleLoop = true; @@ -1014,6 +1051,8 @@ protected Result classifyPrecedence(DecisionState s) { res.guardedIterates += attempt.guardedIterates; res.iterateAccepts += attempt.iterateAccepts; res.frontierIterates += attempt.frontierIterates; + res.guardedObligations += attempt.guardedObligations; + res.obligationAccepts += attempt.obligationAccepts; if (note.length() > 0) note.append(' '); note.append("p").append(c == 0 ? "<=" + cutoffs[0] : c < cutoffs.length ? "=" + (cutoffs[c-1]+1) + ".." + cutoffs[c] @@ -1305,6 +1344,7 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { List> ownRoots = new ArrayList>(); // postfix guard roots entering each state Map guardCandidates = new LinkedHashMap(); // take-vetoed conflict states -> their conflicting alternatives (null for budget escapes, never conflict-analyzed) Map guardIterateCandidates = new LinkedHashMap(); // iterate/exit conflicts vetoed only on foreign consumption -> their conflicting alternatives + Set guardObligationCandidates = new LinkedHashSet(); // iterate/exit states vetoed only by phantom-born obligations (roots in ownRoots) this.currentDecisionRule = s.ruleIndex; Set start = new LinkedHashSet(); @@ -1418,14 +1458,31 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { if (precRuleIndex >= 0 && precClassSubstitutable && precSimpleLoop && conflicting.cardinality() == 2 && conflicting.get(1) && conflicting.get(2)) { - int attest = iterateSubstitutionAttestations(cs); + Set obRoots = new HashSet(); + int attest = iterateSubstitutionAttestations(cs, obRoots); boolean exitForeign = (attest & EXIT_FOREIGN) != 0; boolean exitObligated = (attest & EXIT_OBLIGATED) != 0; boolean iterateReal = (attest & ITERATE_REAL) != 0; if (!exitForeign && !exitObligated && iterateReal) { - res.exactAmbigConflicts.add(conflicting); - acceptAlts.set(d, 1); - continue; + if (obRoots.isEmpty()) { + res.exactAmbigConflicts.add(conflicting); + acceptAlts.set(d, 1); + continue; + } + if (hybridMode) { + // vetoed only by obligations of phantom-born + // frames: a candidate for the guarded-obligation + // iterate accept (resolved after construction, + // once guard roots have propagated) + acceptAlts.set(d, StaticDFA.ESCAPE); + if (ownRoots.get(d) == null) ownRoots.set(d, new HashSet(obRoots)); + else ownRoots.get(d).addAll(obRoots); + guardObligationCandidates.add(d); + res.exactAmbigConflicts.add(conflicting); + continue; + } + // full-table attempts cannot guard: the phantom + // obligations veto (fall through to escape) } if ("veto".equals(System.getProperty("antlr.dfa.debug"))) { System.err.printf("SUBST-VETO d=%d state=%d foreign=%s obligated=%s iterateReal=%s%n", @@ -1450,7 +1507,10 @@ protected boolean buildDFA(DecisionState s, Result res, int depthBound) { // vetoed only by foreign consumption of the exit // lineage: a candidate for the guarded-iterate escape // (resolved after construction, once guard roots have - // propagated) + // propagated); phantom obligations join the guard's + // root set + if (ownRoots.get(d) == null) ownRoots.set(d, new HashSet(obRoots)); + else ownRoots.get(d).addAll(obRoots); guardIterateCandidates.put(d, conflicting); } } @@ -1712,22 +1772,42 @@ else if (abortInfAsOverflow) { } } else if (precRuleIndex >= 0 && precClassSubstitutable && precSimpleLoop - && alts.cardinality() == 2 && alts.get(1) && alts.get(2) - && iterateSubstitutionAttestations(cs) == ITERATE_REAL) { - // Budget-frontier iterate/exit state of a precedence loop: - // no conflict materialized before the cutoff, but the - // substitution attestations (a lineage property, independent - // of any collision) certify that exit can never become - // uniquely viable - its scanned tokens were all consumed by - // the loop discipline and it owes nothing iterate does not - // owe - so the adaptive engine answers iterate whenever it - // terminates: unique iterate, or an ambiguity resolved to - // the minimum alternative. Resolve without the scan. - res.frontierIterates++; - acceptAlts.set(d, 1); - if ("guard".equals(System.getProperty("antlr.dfa.debug"))) { - System.err.printf("FRONTIER-ITERATE d=%d state=%d depth=%d%n", - s.decision, d, stateDepth.get(d)); + && alts.cardinality() == 2 && alts.get(1) && alts.get(2)) { + Set obRoots = new HashSet(); + int frontierAttest = iterateSubstitutionAttestations(cs, obRoots); + if (frontierAttest == ITERATE_REAL && obRoots.isEmpty()) { + // Budget-frontier iterate/exit state of a precedence loop: + // no conflict materialized before the cutoff, but the + // substitution attestations (a lineage property, independent + // of any collision) certify that exit can never become + // uniquely viable - its scanned tokens were all consumed by + // the loop discipline and it owes nothing iterate does not + // owe - so the adaptive engine answers iterate whenever it + // terminates: unique iterate, or an ambiguity resolved to + // the minimum alternative. Resolve without the scan. + res.frontierIterates++; + acceptAlts.set(d, 1); + if ("guard".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FRONTIER-ITERATE d=%d state=%d depth=%d%n", + s.decision, d, stateDepth.get(d)); + } + } + else if (frontierAttest == ITERATE_REAL) { + // Same, but with obligations of phantom-born + // frames: a guarded-obligation candidate (the + // runtime guard defers when such a frame is on + // the real stack) + acceptAlts.set(d, StaticDFA.ESCAPE); + if (ownRoots.get(d) == null) ownRoots.set(d, new HashSet(obRoots)); + else ownRoots.get(d).addAll(obRoots); + guardObligationCandidates.add(d); + if ("guard".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("FRONTIER-GUARD-OBLIGATION d=%d state=%d depth=%d roots=%s%n", + s.decision, d, stateDepth.get(d), new TreeSet(obRoots)); + } + } + else { + acceptAlts.set(d, StaticDFA.ESCAPE); } } else { @@ -1844,11 +1924,12 @@ else if (ls.roots != null) { ownRoots, guardCandidates, guardAlts, res); } if (guard == null && hybridMode && currentPostfixShape == null - && !guardIterateCandidates.isEmpty() && !overflow && !res.sawPredicate) { + && (!guardIterateCandidates.isEmpty() || !guardObligationCandidates.isEmpty()) + && !overflow && !res.sawPredicate) { // iterate/exit conflicts vetoed only on foreign consumption get // a second chance: the guarded-iterate escape guard = finalizeGuardedIterates(s, states, edges, acceptAlts, acceptMasks, - ownRoots, guardIterateCandidates, guardAlts, res); + ownRoots, guardIterateCandidates, guardObligationCandidates, guardAlts, res); } if ("states".equals(System.getProperty("antlr.dfa.debug")) @@ -2055,12 +2136,40 @@ protected GuardData finalizeGuardedIterates(DecisionState s, List acceptMasks, List> ownRoots, Map guardIterateCandidates, + Set guardObligationCandidates, List guardAlts, Result res) { List> through = propagateGuardRoots(states, edges, ownRoots); Set G = new HashSet(); List guarded = new ArrayList(); + for (int d : guardObligationCandidates) { + if (acceptAlts.get(d) != StaticDFA.ESCAPE || acceptMasks.get(d) != 0) continue; + // eligibility was established at the candidate site (iterate + // viability attested, no foreign consumption, no real + // obligation). The guard's roots are uniform: every pending + // position of the rule's base alternatives - the phantom + // descent that would model the caller owing those tokens may + // never reach this conflict's context set (cov4's PRIOR base_ + // frame), but the runtime stack either sits on such an + // invocation or it does not. + Set roots = new HashSet(); + if (through.get(d) != null) roots.addAll(through.get(d)); + for (int i = precBasePendingStates.nextSetBit(0); i >= 0; + i = precBasePendingStates.nextSetBit(i+1)) { + roots.add(i); + } + if (roots.isEmpty()) continue; + acceptAlts.set(d, StaticDFA.GUARDED); + guardAlts.set(d, 1); + guarded.add(d); + G.addAll(roots); + res.guardedObligations++; + if ("guard".equals(System.getProperty("antlr.dfa.debug"))) { + System.err.printf("GUARD-OBLIGATION d=%d state=%d roots=%s%n", + s.decision, d, new TreeSet(roots)); + } + } for (Map.Entry cand : guardIterateCandidates.entrySet()) { int d = cand.getKey(); if (acceptAlts.get(d) != StaticDFA.ESCAPE || acceptMasks.get(d) != 0) continue; @@ -2117,7 +2226,8 @@ protected GuardData finalizeGuardedIterates(DecisionState s, for (int d : guarded) { acceptAlts.set(d, StaticDFA.ESCAPE); guardAlts.set(d, 0); - res.guardedIterates--; + if (guardObligationCandidates.contains(d)) res.guardedObligations--; + else res.guardedIterates--; } return null; } @@ -2132,8 +2242,14 @@ protected GuardData finalizeGuardedIterates(DecisionState s, for (int d : guarded) { acceptAlts.set(d, 1); guardAlts.set(d, 0); - res.guardedIterates--; - res.iterateAccepts++; + if (guardObligationCandidates.contains(d)) { + res.guardedObligations--; + res.obligationAccepts++; + } + else { + res.guardedIterates--; + res.iterateAccepts++; + } } if ("guard".equals(System.getProperty("antlr.dfa.debug"))) { System.err.printf("GUARD-ITERATE-STATIC d=%d states=%s%n", @@ -2567,11 +2683,6 @@ else if (t instanceof WildcardTransition) { ATNConfig advanced = new ATNConfig(c, moveTargets.get(m)); if (precRuleIndex >= 0 && (c.reachesIntoOuterContext & BOUNDARY_TAINT) != 0) { - // any consumption by a boundary-popped lineage marks the - // descent separated (CONSUMED_TAINT): re-descent frames born - // past this point model real separator-led continuations, - // not juxtaposition phantoms (see phantomFrameKeys) - advanced.reachesIntoOuterContext |= CONSUMED_TAINT; if (isLoopConsumption(c)) { // loop-block consumption by a boundary-popped // config: the phantom consumer is an enclosing @@ -2754,22 +2865,18 @@ else if (contextDepth(config.context) >= currentDepthBound ATNConfig callee = new ATNConfig(config, rt.target, newCtx); if (config.alt == 2 && !newCtx.isEmpty()) { // phantom re-descent birth (see phantomFrameKeys): an - // invocation from a wildcard-born lineage that consumed - // NOTHING since the pop hypothesizes a juxtaposed descent - // no real stack offers. A lineage that already consumed a - // separator (CONSUMED_TAINT: the PRIOR of the self- - // referential base alternative, the = of a boolean - // equality, an argument-list , or () models a real - // continuation shape - cov4's CONNECT BY PRIOR B.ID = ... - // is parsed through exactly such a frame - so its - // obligations stand. Alt-2-scoped: exit-lineage chains - // only ever carry exit-born frame values, so clean - // iterate births of the same value must not poison the - // classification. + // invocation from a wildcard-born lineage hypothesizes a + // juxtaposed descent the analysis cannot prove a real + // stack offers. Its token obligations are not discharged + // statically, though: they become guard roots and the + // iterate accept defers to the adaptive engine when the + // frame is on the real stack (see finalizeGuardedIterates). + // Alt-2-scoped: exit-lineage chains only ever carry + // exit-born frame values, so clean iterate births of the + // same value must not poison the classification. boolean phantomBirth = - (config.reachesIntoOuterContext & CONSUMED_TAINT) == 0 - && ((config.reachesIntoOuterContext & BOUNDARY_TAINT) != 0 - || ctxContainsWildcard(config.context)); + (config.reachesIntoOuterContext & BOUNDARY_TAINT) != 0 + || ctxContainsWildcard(config.context); (phantomBirth ? phantomFrameKeys : realFrameKeys) .add(frameKey(newCtx)); } @@ -2938,7 +3045,8 @@ else if (!bottomFrameIs(p, endState, visited)) { * {@link #ITERATE_REAL}; {@code ITERATE_REAL|EXIT_FOREIGN} admits the * state to the guarded-iterate escape. */ - protected int iterateSubstitutionAttestations(Set cs) { + protected int iterateSubstitutionAttestations(Set cs, + Set phantomObRoots) { int attest = 0; for (ATNConfig c : cs) { if (c.alt == 2) { @@ -2956,17 +3064,19 @@ protected int iterateSubstitutionAttestations(Set cs) { // position owing ',' or '>>', which has no iterate-side // counterpart - there the runtime can kill iterate with deeper // lookahead and legitimately predict exit. Frames born from a - // phantom re-descent ({@link #phantomFrameKeys}) are skipped: - // they hypothesize a juxtaposed fresh descent no real stack - // offers, so their obligations are dead. + // phantom re-descent ({@link #phantomFrameKeys}) are no static + // veto: their obligations are collected as guard roots and the + // iterate accept defers when such a frame is on the real + // stack (see finalizeGuardedIterates). if (c.state.ruleIndex == precRuleIndex && precPendingStates.get(c.state.stateNumber) - && hasPendingPrecReturn(c.context)) { + && hasPendingPrecReturn(c.context, phantomObRoots)) { attest |= EXIT_OBLIGATED; } if (hasObligatedReturn(c.context, java.util.Collections.newSetFromMap( - new java.util.IdentityHashMap()))) { + new java.util.IdentityHashMap()), + phantomObRoots)) { attest |= EXIT_OBLIGATED; } } @@ -3034,16 +3144,25 @@ private static long avalanche(long h) { return h; } - private boolean hasPendingPrecReturn(PredictionContext ctx) { + /** Is there a pending same-rule return in the context that is NOT + * phantom-born? Phantom-born obligation slots are collected into + * {@code phantomRoots} (nullable) as guard roots instead of being + * discharged outright: the runtime stack guard defers the iterate + * accept exactly when a discharged frame is on the real stack. */ + private boolean hasPendingPrecReturn(PredictionContext ctx, Set phantomRoots) { if (ctx == null || ctx.isEmpty()) return false; for (int i = 0; i < ctx.size(); i++) { int rs = ctx.getReturnState(i); - if (rs != PredictionContext.EMPTY_RETURN_STATE - && !phantomSlot(frameKey(ctx.getParent(i)), rs)) { + if (rs != PredictionContext.EMPTY_RETURN_STATE) { ATNState st = atn.states.get(rs); if (st.ruleIndex == precRuleIndex && precPendingStates.get(rs)) { - return true; + if (phantomSlot(frameKey(ctx.getParent(i)), rs)) { + if (phantomRoots != null) phantomRoots.add(rs); + } + else { + return true; + } } } } @@ -3064,23 +3183,32 @@ private boolean phantomSlot(long parentKey, int returnState) { * token obligation outside the iteration-start region - a frame of * the precedence rule that cannot be discharged by iterating (see * {@link #precPendingStates})? Phantom-born frames - * ({@link #phantomContexts}) are skipped: they model a juxtaposed - * re-descent that no real stack can realize, so their obligations - * cannot make the exit side uniquely viable. + * ({@link #phantomFrameKeys}) are no static veto either: their + * realizability is stack-dependent, so they are collected as guard + * roots ({@code phantomRoots}) and the iterate accept defers to the + * adaptive engine exactly when such a frame is on the real parse + * stack. */ - private boolean hasObligatedReturn(PredictionContext ctx, Set visited) { + private boolean hasObligatedReturn(PredictionContext ctx, Set visited, + Set phantomRoots) { if (ctx == null || ctx.isEmpty() || !visited.add(ctx)) return false; for (int i = 0; i < ctx.size(); i++) { int rs = ctx.getReturnState(i); if (rs != PredictionContext.EMPTY_RETURN_STATE) { ATNState st = atn.states.get(rs); - boolean phantom = phantomSlot(frameKey(ctx.getParent(i)), rs); - if (!phantom - && st.ruleIndex == precRuleIndex + if (st.ruleIndex == precRuleIndex && precPendingStates.get(rs)) { - return true; + if (phantomSlot(frameKey(ctx.getParent(i)), rs)) { + // phantom-born frame: dischargeable obligation, + // realized only when the frame is on the real + // stack - a guard root, not a static veto + if (phantomRoots != null) phantomRoots.add(rs); + } + else { + return true; + } } - if (hasObligatedReturn(ctx.getParent(i), visited)) return true; + if (hasObligatedReturn(ctx.getParent(i), visited, phantomRoots)) return true; } } return false; @@ -3656,15 +3784,17 @@ else if (r.dfa == null) { if (utrust > 0) { buf.append(String.format("utrust: %d conflict states resolved to min-alt%n", utrust)); } - int iterGuards = 0, iterAccepts = 0, iterFrontier = 0; + int iterGuards = 0, iterAccepts = 0, iterFrontier = 0, obGuards = 0, obAccepts = 0; for (Result r : results) { iterGuards += r.guardedIterates; iterAccepts += r.iterateAccepts; iterFrontier += r.frontierIterates; + obGuards += r.guardedObligations; + obAccepts += r.obligationAccepts; } - if (iterGuards > 0 || iterAccepts > 0 || iterFrontier > 0) { - buf.append(String.format("iterate-guard: %d conflict states guarded, %d resolved outright, %d frontier states resolved%n", - iterGuards, iterAccepts, iterFrontier)); + if (iterGuards > 0 || iterAccepts > 0 || iterFrontier > 0 || obGuards > 0 || obAccepts > 0) { + buf.append(String.format("iterate-guard: %d conflict states guarded, %d resolved outright, %d frontier states resolved, %d obligation states guarded, %d resolved outright%n", + iterGuards, iterAccepts, iterFrontier, obGuards, obAccepts)); } int descentPlans = 0, descentMasks = 0; for (Result r : results) { From 578f1ff1c460e60860ac08688f8795600a7f7c56 Mon Sep 17 00:00:00 2001 From: Bo Lin Date: Fri, 31 Jul 2026 16:04:15 -0400 Subject: [PATCH 48/48] Clean up loose ends. --- .gitignore | 1 + runtime/Rust/src/follow_sets.rs | 10 ++++-- runtime/Rust/src/lib.rs | 4 +-- runtime/Rust/src/parser.rs | 36 +++++++++---------- runtime/Rust/src/semantic_context.rs | 9 ++--- runtime/Rust/src/serialized_ints.rs | 21 +++++------ runtime/Rust/tests/fuzz_differential_tests.rs | 4 +-- runtime/Rust/tests/static_dfa_tests.rs | 12 +++---- .../v4/tool/templates/codegen/Rust/Rust.stg | 19 +++++----- tool/src/org/antlr/v4/tool/Grammar.java | 6 ++++ 10 files changed, 61 insertions(+), 61 deletions(-) diff --git a/.gitignore b/.gitignore index b6ea50bc29..df092f0147 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ build/ dist/ lib/ user.build.properties +.factorypath # MacOSX files .DS_Store diff --git a/runtime/Rust/src/follow_sets.rs b/runtime/Rust/src/follow_sets.rs index f9976aeaaf..8b212ed239 100644 --- a/runtime/Rust/src/follow_sets.rs +++ b/runtime/Rust/src/follow_sets.rs @@ -26,7 +26,6 @@ use std::sync::OnceLock; use crate::atn::ATN; -use crate::token::TOKEN_EPSILON; use crate::transition::TransitionType; /// Per invocation-site continuation sets (see module docs). Indexed by @@ -82,7 +81,9 @@ impl FollowSets { if let Some(label) = tr.get_label() { for iv in label { for tok in iv.a..=iv.b.min(max_token) { - if tok >= crate::token::TOKEN_MIN_USER_TOKEN_TYPE && set_bit(acc, tok) { + if tok >= crate::token::TOKEN_MIN_USER_TOKEN_TYPE + && set_bit(acc, tok) + { changed = true; } } @@ -168,7 +169,10 @@ impl FollowSets { } } } - FollowSets { first: site_first, nullable: site_nullable } + FollowSets { + first: site_first, + nullable: site_nullable, + } } /// Does the continuation after the invocation at call-site `state` diff --git a/runtime/Rust/src/lib.rs b/runtime/Rust/src/lib.rs index 04a3773412..d7ac9353a6 100644 --- a/runtime/Rust/src/lib.rs +++ b/runtime/Rust/src/lib.rs @@ -91,11 +91,11 @@ pub mod atn; pub mod atn_config_set; #[doc(hidden)] pub mod atn_deserializer; -pub mod follow_sets; pub mod common_token_stream; pub mod error_listener; pub mod error_strategy; pub mod errors; +pub mod follow_sets; pub mod input_stream; pub mod lexer; #[doc(hidden)] @@ -112,9 +112,9 @@ mod utils; //pub mod tokenstream_rewriter_test; mod atn_type; // mod context_factory; +pub mod prelude; pub mod rule_context; pub mod vocabulary; -pub mod prelude; // ======= Re-exports ======== #[cfg(feature = "stacker")] diff --git a/runtime/Rust/src/parser.rs b/runtime/Rust/src/parser.rs index 6272e5e726..eece05cd88 100644 --- a/runtime/Rust/src/parser.rs +++ b/runtime/Rust/src/parser.rs @@ -495,22 +495,6 @@ where self.global_cache_threshold = threshold; } - /// Predict the alternative of a decision from its statically-precomputed - /// SLL prediction DFA (generated by the ANTLR tool's `-Xstatic-dfa` - /// option and decoded into [`crate::atn::ATN::static_dfas`] together - /// with the ATN) instead of `adaptive_predict`. Walks the table over - /// `LA(1..n)` without consuming input; no ATN simulation, no - /// per-prediction allocation. - /// - /// Returns the predicted alternative (1-based, decision-transition - /// numbering identical to `adaptive_predict`), or - /// [`crate::atn::INVALID_ALT`] (0) when the table defers the prediction - /// to the adaptive engine - a hybrid table's escape state, or a - /// precedence class without a table. Generated call sites rerun such - /// predictions through `adaptive_predict` (sound: the walker never - /// consumes input). A lookahead token matching no table edge produces a - /// `NoViableAlt` error anchored at the decision start token, matching - /// `adaptive_predict`'s convention. /// Diagnostic escape tracing for `dfa_predict` (`ANTLR_DFA_TRACE=1`): /// logs every prediction the static tables defer to the adaptive /// engine, the tool for finding which decisions a given input keeps @@ -531,6 +515,22 @@ where false } + /// Predict the alternative of a decision from its statically-precomputed + /// SLL prediction DFA (generated by the ANTLR tool's `-Xstatic-dfa` + /// option and decoded into [`crate::atn::ATN::static_dfas`] together + /// with the ATN) instead of `adaptive_predict`. Walks the table over + /// `LA(1..n)` without consuming input; no ATN simulation, no + /// per-prediction allocation. + /// + /// Returns the predicted alternative (1-based, decision-transition + /// numbering identical to `adaptive_predict`), or + /// [`crate::atn::INVALID_ALT`] (0) when the table defers the prediction + /// to the adaptive engine - a hybrid table's escape state, or a + /// precedence class without a table. Generated call sites rerun such + /// predictions through `adaptive_predict` (sound: the walker never + /// consumes input). A lookahead token matching no table edge produces a + /// `NoViableAlt` error anchored at the decision start token, matching + /// `adaptive_predict`'s convention. pub fn dfa_predict(&mut self, decision: i32) -> Result { let mask = self.dfa_walk(decision)?; if mask == 0 || !mask.is_power_of_two() { @@ -573,10 +573,6 @@ where if inv < 0 { break; } - if std::env::var_os("DBG_FOLLOW").is_some() { - eprintln!("FOLLOW token={} inv={} contains={} nullable={}", - token, inv, sets.contains(inv as usize, token), sets.nullable(inv as usize)); - } if sets.contains(inv as usize, token) { return true; } diff --git a/runtime/Rust/src/semantic_context.rs b/runtime/Rust/src/semantic_context.rs index 7990997bd4..0f7097dc0a 100644 --- a/runtime/Rust/src/semantic_context.rs +++ b/runtime/Rust/src/semantic_context.rs @@ -114,12 +114,9 @@ impl<'ephemeral> SemanticContext<'ephemeral> { let evaluated = context.eval_precedence(scratch, parser, outer_context); differs |= evaluated.is_some() && context == evaluated.unwrap(); - if let Some(evaluated) = evaluated { - if *evaluated != Self::NONE { - operands.push(evaluated); - } - } else { - return None; + let evaluated = evaluated?; + if *evaluated != Self::NONE { + operands.push(evaluated); } } diff --git a/runtime/Rust/src/serialized_ints.rs b/runtime/Rust/src/serialized_ints.rs index 607041573d..bcbae056be 100644 --- a/runtime/Rust/src/serialized_ints.rs +++ b/runtime/Rust/src/serialized_ints.rs @@ -36,18 +36,15 @@ impl<'a> Decoder<'a> { fn next_byte(&mut self) -> Option { while self.bits < 8 { let c = loop { - match self.segments.get(self.segment) { - None => return None, - Some(segment) => match segment.as_bytes().get(self.at) { - None => { - self.segment += 1; - self.at = 0; - } - Some(&c) => { - self.at += 1; - break c; - } - }, + match self.segments.get(self.segment)?.as_bytes().get(self.at) { + None => { + self.segment += 1; + self.at = 0; + } + Some(&c) => { + self.at += 1; + break c; + } } }; let v = match c { diff --git a/runtime/Rust/tests/fuzz_differential_tests.rs b/runtime/Rust/tests/fuzz_differential_tests.rs index dcbc185541..f77db92aa7 100644 --- a/runtime/Rust/tests/fuzz_differential_tests.rs +++ b/runtime/Rust/tests/fuzz_differential_tests.rs @@ -96,8 +96,8 @@ fn gen_expr(rng: &mut Rng, depth: usize, out: &mut String) { if depth == 0 || rng.below(4) == 0 { // atom match rng.below(6) { - 0 => out.push_str("x"), - 1 => out.push_str("1"), + 0 => out.push('x'), + 1 => out.push('1'), 2 => out.push_str("as"), // soft keyword as identifier 3 => out.push_str("a.b"), 4 => { diff --git a/runtime/Rust/tests/static_dfa_tests.rs b/runtime/Rust/tests/static_dfa_tests.rs index 9c593e359d..fb8b10625f 100644 --- a/runtime/Rust/tests/static_dfa_tests.rs +++ b/runtime/Rust/tests/static_dfa_tests.rs @@ -139,15 +139,15 @@ fn test_exact_ambiguity_min_alt() { fn test_no_viable_alt_handling() { // 'create foo' - fails inside the LL(2) DFA at depth 2 let r = parse("create foo", "stat"); - match r { - Ok(tree) => assert!(tree.contains("create")), // recovered parse - Err(_) => {} // unrecoverable is fine too + if let Ok(tree) = r { + assert!(tree.contains("create")); // recovered parse } + // unrecoverable is fine too + // dotted name that ends at a dot: cyclic DFA hits EOF mid-scan let r = parse("aa.bb.", "expr"); - match r { - Ok(tree) => assert!(tree.contains("aa")), - Err(_) => {} + if let Ok(tree) = r { + assert!(tree.contains("aa")) } } diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg index 153fdf8848..053c62279b 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Rust/Rust.stg @@ -737,9 +737,8 @@ FactoredTailArm(t, body) ::= << descentMaskPredict(choice, groups) ::= << { let _m = .base.dfa_predict_mask()?; match _m { - 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), - x if (x & (x-1)) != 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), + x if x == 0 || (x & (x-1)) != 0 => 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32), m => m, } } >> @@ -760,23 +759,23 @@ DescentGroup(g, tails) ::= << Ok(_node) => { if .base.syntax_error_count() != _neutral_state.2 { .base.end_neutral_parse(&_neutral_state); - // errorful neutral parse: throw its result away and + .get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) +!> 1u64.wrapping_shl((.get_interpreter().adaptive_predict(,&mut .base)? - 1) as u32) } else { - // the tail token decides on the post-prefix stream. + .input.la(1); match _t { +!> let _tailbit = { let _t = .input.la(1); match _t { _ => Some()None, } }; match _tailbit { Some(bit) => { - .base.start_resume(dbt_antlr4::tree::NodeInner::as_node(_node), RULE_); + .base.start_resume(_node.as_node(), RULE_); .base.end_neutral_parse(&_neutral_state); bit } @@ -898,8 +897,8 @@ cases(tokens) ::= << _ }; separator="|",wrap> >> +// InvokeRule InvokeRule(r, argExprsChunks) ::= << -/*InvokeRule */ .base.set_state(); ._rec(,)?})> >> @@ -1194,13 +1193,13 @@ impl\<'input: 'arena, 'arena, Tok: Token + 'input> Ext\<'inp let tmp = unsafe { std::ptr::read(base_ctx) }; ContextAll::(tmp.morph(|ext_src| Self::new(ext_src))) }; - // replace + forget, NOT assignment: the new value's children Vec + mut ContextAll\<'input, 'arena, Tok\>), ctx); + !>let _old = std::mem::replace(dbt_antlr4::cast_unchecked!(src => mut ContextAll\<'input, 'arena, Tok\>), ctx); std::mem::forget(_old); src.set_invoking_state(invoking_state); src.node_tag = \\>::node_tag(); diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index e5c114a6c8..4e089d37bb 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -93,8 +93,14 @@ public class Grammar implements AttributeResolver { } public static final Set parseRuleOptions = new HashSet<>(); + static { + parseRuleOptions.add("logical"); + } public static final Set parserBlockOptions = new HashSet(); + static { + parseRuleOptions.add("logical"); + } public static final Set lexerBlockOptions = new HashSet();