antlr4ng
Version:
Alternative JavaScript/TypeScript runtime for ANTLR4
5,585 lines • 168 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/IntStream.ts
var IntStream;
((IntStream2) => {
IntStream2.EOF = -1;
IntStream2.UNKNOWN_SOURCE_NAME = "<unknown>";
})(IntStream || (IntStream = {}));
// src/Token.ts
var Token;
((Token2) => {
Token2.INVALID_TYPE = 0;
Token2.EPSILON = -2;
Token2.MIN_USER_TOKEN_TYPE = 1;
Token2.EOF = IntStream.EOF;
Token2.DEFAULT_CHANNEL = 0;
Token2.HIDDEN_CHANNEL = 1;
Token2.MIN_USER_CHANNEL_VALUE = 2;
})(Token || (Token = {}));
var isToken = /* @__PURE__ */ __name((candidate) => {
const token = candidate;
return token.tokenSource !== void 0 && token.channel !== void 0;
}, "isToken");
// src/BaseErrorListener.ts
var BaseErrorListener = class {
static {
__name(this, "BaseErrorListener");
}
syntaxError(recognizer, offendingSymbol, line, column, msg, e) {
}
reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) {
}
reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs) {
}
reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs) {
}
};
// src/ConsoleErrorListener.ts
var ConsoleErrorListener = class _ConsoleErrorListener extends BaseErrorListener {
static {
__name(this, "ConsoleErrorListener");
}
/**
* Provides a default instance of {@link ConsoleErrorListener}.
*/
static instance = new _ConsoleErrorListener();
syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, _e) {
console.error("line " + line + ":" + charPositionInLine + " " + msg);
}
};
// src/ProxyErrorListener.ts
var ProxyErrorListener = class extends BaseErrorListener {
constructor(delegates) {
super();
this.delegates = delegates;
return this;
}
static {
__name(this, "ProxyErrorListener");
}
syntaxError(recognizer, offendingSymbol, line, column, msg, e) {
this.delegates.forEach((d) => {
d.syntaxError(recognizer, offendingSymbol, line, column, msg, e);
});
}
reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) {
this.delegates.forEach((d) => {
d.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs);
});
}
reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs) {
this.delegates.forEach((d) => {
d.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs);
});
}
reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs) {
this.delegates.forEach((d) => {
d.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs);
});
}
};
// src/Recognizer.ts
var Recognizer = class _Recognizer {
static {
__name(this, "Recognizer");
}
static EOF = -1;
static tokenTypeMapCache = /* @__PURE__ */ new Map();
static ruleIndexMapCache = /* @__PURE__ */ new Map();
interpreter;
listeners = [ConsoleErrorListener.instance];
stateNumber = -1;
checkVersion(toolVersion) {
const runtimeVersion = "4.13.1";
if (runtimeVersion !== toolVersion) {
console.error("ANTLR runtime and generated code versions disagree: " + runtimeVersion + "!=" + toolVersion);
}
}
addErrorListener(listener) {
this.listeners.push(listener);
}
removeErrorListeners() {
this.listeners = [];
}
removeErrorListener(listener) {
for (let i = 0; i < this.listeners.length; i++) {
if (this.listeners[i] === listener) {
this.listeners.splice(i, 1);
return;
}
}
}
getErrorListeners() {
return this.listeners;
}
getTokenTypeMap() {
const vocabulary = this.vocabulary;
let result = _Recognizer.tokenTypeMapCache.get(vocabulary);
if (!result) {
result = /* @__PURE__ */ new Map();
for (let i = 0; i <= this.atn.maxTokenType; i++) {
const literalName = vocabulary.getLiteralName(i);
if (literalName) {
result.set(literalName, i);
}
const symbolicName = vocabulary.getSymbolicName(i);
if (symbolicName) {
result.set(symbolicName, i);
}
}
result.set("EOF", Token.EOF);
_Recognizer.tokenTypeMapCache.set(vocabulary, result);
}
return result;
}
/**
* Get a map from rule names to rule indexes.
* Used for XPath and tree pattern compilation.
*/
getRuleIndexMap() {
const ruleNames = this.ruleNames;
let result = _Recognizer.ruleIndexMapCache.get(ruleNames);
if (!result) {
result = /* @__PURE__ */ new Map();
ruleNames.forEach((ruleName, idx) => {
return result.set(ruleName, idx);
});
_Recognizer.ruleIndexMapCache.set(ruleNames, result);
}
return result;
}
getTokenType(tokenName) {
const ttype = this.getTokenTypeMap().get(tokenName);
if (ttype) {
return ttype;
}
return Token.INVALID_TYPE;
}
/** What is the error header, normally line/character position information? */
getErrorHeader(e) {
const line = e.offendingToken?.line;
const column = e.offendingToken?.column;
return "line " + line + ":" + column;
}
get errorListenerDispatch() {
return new ProxyErrorListener(this.listeners);
}
/**
* subclass needs to override these if there are semantic predicates or actions
* that the ATN interp needs to execute
*/
sempred(_localctx, _ruleIndex, _actionIndex) {
return true;
}
// TODO: make localCtx an optional parameter, not optional null.
precpred(_localctx, _precedence) {
return true;
}
action(_localctx, _ruleIndex, _actionIndex) {
}
get atn() {
return this.interpreter.atn;
}
get state() {
return this.stateNumber;
}
set state(state) {
this.stateNumber = state;
}
getParseInfo() {
return void 0;
}
};
// src/CommonToken.ts
var CommonToken = class _CommonToken {
static {
__name(this, "CommonToken");
}
/**
* An empty tuple which is used as the default value of
* {@link source} for tokens that do not have a source.
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
static EMPTY_SOURCE = [null, null];
/**
* These properties share a field to reduce the memory footprint of
* {@link CommonToken}. Tokens created by a {@link CommonTokenFactory} from
* the same source and input stream share a reference to the same
* {@link Pair} containing these values.
*/
source;
tokenIndex;
start;
stop;
/**
* This is the backing field for {@link #getType} and {@link #setType}.
*/
type;
/**
* The (one-based) line number on which the 1st character of this token was.
*/
line;
/**
* The zero-based index of the first character position in its line.
*/
column;
/**
* The token's channel.
*/
channel;
/**
* This is the backing field for {@link getText} when the token text is
* explicitly set in the constructor or via {@link setText}.
*/
#text;
constructor(details) {
this.type = details.type;
this.source = details.source;
this.tokenIndex = details.tokenIndex ?? -1;
this.line = details.line ?? 0;
this.column = details.column ?? -1;
this.channel = details.channel ?? Token.DEFAULT_CHANNEL;
this.start = details.start ?? 0;
this.stop = details.stop ?? 0;
this.#text = details.text;
if (details.line === void 0 && details.source[0] !== null) {
this.line = details.source[0].line;
}
if (details.column === void 0 && details.source[0] !== null) {
this.column = details.source[0].column;
}
}
/**
* Constructs a new {@link CommonToken} as a copy of another {@link Token}.
*
* If `token` is also a {@link CommonToken} instance, the newly
* constructed token will share a reference to the {@link #text} field and
* the {@link Pair} stored in {@link source}. Otherwise, {@link text} will
* be assigned the result of calling {@link getText}, and {@link source}
* will be constructed from the result of {@link Token.getTokenSource} and
* {@link Token#getInputStream}.
*
* @param token The token to copy.
*/
static fromToken(token) {
const source = [token.tokenSource, token.inputStream];
return new _CommonToken({
type: token.type,
line: token.line,
tokenIndex: token.tokenIndex,
column: token.column,
channel: token.channel,
start: token.start,
stop: token.stop,
text: token.text,
source
});
}
/**
* Constructs a new {@link CommonToken} with the specified token type and text.
*
* @param type The token type.
* @param text The text of the token.
*/
static fromType(type, text) {
return new _CommonToken({ type, text, source: _CommonToken.EMPTY_SOURCE });
}
static fromSource(source, type, channel, start, stop) {
return new _CommonToken({ type, channel, start, stop, source });
}
get tokenSource() {
return this.source[0];
}
get inputStream() {
return this.source[1];
}
set inputStream(input) {
this.source[1] = input;
}
/**
* Constructs a new {@link CommonToken} as a copy of another {@link Token}.
*
* If `oldToken` is also a {@link CommonToken} instance, the newly
* constructed token will share a reference to the {@link text} field and
* the {@link Pair} stored in {@link source}. Otherwise, {@link text} will
* be assigned the result of calling {@link getText}, and {@link source}
* will be constructed from the result of {@link Token.getTokenSource} and
* {@link Token.getInputStream}.
*/
clone() {
const t = new _CommonToken({
source: this.source,
type: this.type,
channel: this.channel,
start: this.start,
stop: this.stop,
tokenIndex: this.tokenIndex,
line: this.line,
column: this.column,
text: this.#text
});
return t;
}
toString(recognizer) {
let channelStr = "";
if (this.channel > 0) {
channelStr = ",channel=" + this.channel;
}
let text = this.text;
if (text) {
text = text.replace(/\n/g, "\\n");
text = text.replace(/\r/g, "\\r");
text = text.replace(/\t/g, "\\t");
} else {
text = "<no text>";
}
let typeString = String(this.type);
if (recognizer) {
typeString = recognizer.vocabulary.getDisplayName(this.type) ?? "<unknown>";
}
return "[@" + this.tokenIndex + "," + this.start + ":" + this.stop + "='" + text + "',<" + typeString + ">" + channelStr + "," + this.line + ":" + this.column + "]";
}
get text() {
if (this.#text !== void 0) {
return this.#text;
}
const input = this.inputStream;
if (!input) {
return void 0;
}
const n2 = input.size;
if (this.start < n2 && this.stop < n2) {
return input.getTextFromRange(this.start, this.stop);
}
return "<EOF>";
}
set text(text) {
this.#text = text;
}
// WritableToken implementation
setText(text) {
this.#text = text;
}
setType(ttype) {
this.type = ttype;
}
setLine(line) {
this.line = line;
}
setCharPositionInLine(pos) {
this.column = pos;
}
setChannel(channel) {
this.channel = channel;
}
setTokenIndex(index) {
this.tokenIndex = index;
}
};
// src/CommonTokenFactory.ts
var CommonTokenFactory = class _CommonTokenFactory {
static {
__name(this, "CommonTokenFactory");
}
/**
* The default {@link CommonTokenFactory} instance.
*
*
* This token factory does not explicitly copy token text when constructing
* tokens.
*/
static DEFAULT = new _CommonTokenFactory();
/**
* Indicates whether {@link CommonToken.setText} should be called after
* constructing tokens to explicitly set the text. This is useful for cases
* where the input stream might not be able to provide arbitrary substrings
* of text from the input after the lexer creates a token (e.g. the
* implementation of {@link CharStream.getText} in
* {@link UnbufferedCharStream} throws an
* {@link UnsupportedOperationException}). Explicitly setting the token text
* allows {@link Token.getText} to be called at any time regardless of the
* input stream implementation.
*
*
* The default value is `false` to avoid the performance and memory
* overhead of copying text for every token unless explicitly requested.
*/
copyText = false;
constructor(copyText) {
this.copyText = copyText ?? false;
}
create(source, type, text, channel, start, stop, line, column) {
const t = CommonToken.fromSource(source, type, channel, start, stop);
t.line = line;
t.column = column;
if (text) {
t.text = text;
} else if (this.copyText && source[1] !== null) {
t.text = source[1].getTextFromRange(start, stop);
}
return t;
}
};
// src/RecognitionException.ts
var RecognitionException = class _RecognitionException extends Error {
static {
__name(this, "RecognitionException");
}
ctx;
/**
* The current {@link Token} when an error occurred. Since not all streams
* support accessing symbols by index, we have to track the {@link Token}
* instance itself
*/
offendingToken = null;
/**
* Get the ATN state number the parser was in at the time the error
* occurred. For {@link NoViableAltException} and
* {@link LexerNoViableAltException} exceptions, this is the
* {@link DecisionState} number. For others, it is the state whose outgoing
* edge we couldn't match.
*/
offendingState = -1;
recognizer;
input;
constructor(params) {
super(params.message);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, _RecognitionException);
}
this.message = params.message;
this.recognizer = params.recognizer;
this.input = params.input;
this.ctx = params.ctx;
if (this.recognizer !== null) {
this.offendingState = this.recognizer.state;
}
}
/**
* Gets the set of input symbols which could potentially follow the
* previously matched symbol at the time this exception was thrown.
*
* If the set of expected tokens is not known and could not be computed,
* this method returns `null`.
*
* @returns The set of token types that could potentially follow the current
* state in the ATN, or `null` if the information is not available.
*/
getExpectedTokens() {
if (this.recognizer !== null && this.ctx !== null) {
return this.recognizer.atn.getExpectedTokens(this.offendingState, this.ctx);
} else {
return null;
}
}
// If the state number is not known, this method returns -1.
toString() {
return this.message;
}
};
// src/LexerNoViableAltException.ts
var LexerNoViableAltException = class extends RecognitionException {
static {
__name(this, "LexerNoViableAltException");
}
startIndex;
deadEndConfigs;
constructor(lexer, input, startIndex, deadEndConfigs) {
super({ message: "", recognizer: lexer, input, ctx: null });
this.startIndex = startIndex;
this.deadEndConfigs = deadEndConfigs;
}
toString() {
let symbol = "";
if (this.input && this.startIndex >= 0 && this.startIndex < this.input.size) {
symbol = this.input.getTextFromRange(this.startIndex, this.startIndex);
}
return `LexerNoViableAltException(${symbol})`;
}
};
// src/Lexer.ts
var Lexer = class _Lexer extends Recognizer {
static {
__name(this, "Lexer");
}
static DEFAULT_MODE = 0;
static MORE = -2;
static SKIP = -3;
static DEFAULT_TOKEN_CHANNEL = Token.DEFAULT_CHANNEL;
static HIDDEN = Token.HIDDEN_CHANNEL;
options = {
minDFAEdge: 0,
maxDFAEdge: 256,
minCodePoint: 0,
maxCodePoint: 1114111
};
/**
* What character index in the stream did the current token start at?
* Needed, for example, to get the text for current token. Set at
* the start of nextToken.
*/
tokenStartCharIndex = -1;
/** The channel number for the current token */
channel = 0;
/** The token type for the current token */
type = 0;
mode = _Lexer.DEFAULT_MODE;
/** The start column of the current token (the one that was last read by `nextToken`). */
currentTokenColumn = 0;
/**
* The line on which the first character of the current token (the one that was last read by `nextToken`) resides.
*/
currentTokenStartLine = 0;
input;
/**
* The goal of all lexer rules/methods is to create a token object.
* This is an instance variable as multiple rules may collaborate to
* create a single token. nextToken will return this object after
* matching lexer rule(s). If you subclass to allow multiple token
* emissions, then set this to the last token to be matched or
* something non-null so that the auto token emit mechanism will not
* emit another token.
*/
token = null;
/**
* Once we see EOF on char stream, next token will be EOF.
* If you have DONE : EOF ; then you see DONE EOF.
*/
hitEOF = false;
factory;
#modeStack = [];
/**
* The text to be used for the next token. If this is not null, then the text
* for the next token is fixed and is not subject to change in the normal
* workflow of the lexer.
*/
#text;
constructor(input, options) {
super();
this.options = { ...this.options, ...options };
this.input = input;
this.factory = CommonTokenFactory.DEFAULT;
}
reset(seekBack = true) {
if (seekBack) {
this.input.seek(0);
}
this.token = null;
this.type = Token.INVALID_TYPE;
this.channel = Token.DEFAULT_CHANNEL;
this.tokenStartCharIndex = -1;
this.currentTokenColumn = -1;
this.currentTokenStartLine = -1;
this.#text = void 0;
this.hitEOF = false;
this.mode = _Lexer.DEFAULT_MODE;
this.#modeStack = [];
this.interpreter.reset();
}
/** @returns a token from this source; i.e., match a token on the char stream. */
nextToken() {
if (this.input === null) {
throw new Error("nextToken requires a non-null input stream.");
}
const tokenStartMarker = this.input.mark();
try {
while (true) {
if (this.hitEOF) {
this.emitEOF();
return this.token;
}
this.token = null;
this.channel = Token.DEFAULT_CHANNEL;
this.tokenStartCharIndex = this.input.index;
this.currentTokenColumn = this.interpreter.column;
this.currentTokenStartLine = this.interpreter.line;
this.#text = void 0;
let continueOuter = false;
while (true) {
this.type = Token.INVALID_TYPE;
let ttype = _Lexer.SKIP;
try {
ttype = this.interpreter.match(this.input, this.mode);
} catch (e) {
if (e instanceof LexerNoViableAltException) {
this.notifyListeners(e);
this.recover(e);
} else {
throw e;
}
}
if (this.input.LA(1) === Token.EOF) {
this.hitEOF = true;
}
if (this.type === Token.INVALID_TYPE) {
this.type = ttype;
}
if (this.type === _Lexer.SKIP) {
continueOuter = true;
break;
}
if (this.type !== _Lexer.MORE) {
break;
}
}
if (continueOuter) {
continue;
}
if (this.token === null) {
this.emit();
}
return this.token;
}
} finally {
this.input.release(tokenStartMarker);
}
}
/**
* Instruct the lexer to skip creating a token for current lexer rule
* and look for another token. nextToken() knows to keep looking when
* a lexer rule finishes with token set to SKIP_TOKEN. Recall that
* if token==null at end of any token rule, it creates one for you
* and emits it.
*/
skip() {
this.type = _Lexer.SKIP;
}
more() {
this.type = _Lexer.MORE;
}
pushMode(m2) {
if (LexerATNSimulator.debug) {
console.log("pushMode " + m2);
}
this.#modeStack.push(this.mode);
this.mode = m2;
}
popMode() {
if (this.#modeStack.length === 0) {
throw new Error("Empty Stack");
}
if (LexerATNSimulator.debug) {
console.log("popMode back to " + this.#modeStack.slice(0, -1));
}
this.mode = this.#modeStack.pop();
return this.mode;
}
get modeStack() {
return this.#modeStack;
}
/**
* By default does not support multiple emits per nextToken invocation
* for efficiency reasons. Subclass and override this method, nextToken,
* and getToken (to push tokens into a list and pull from that list
* rather than a single variable as this implementation does).
*/
emitToken(token) {
this.token = token;
}
/**
* The standard method called to automatically emit a token at the
* outermost lexical rule. The token object should point into the
* char buffer start..stop. If there is a text override in 'text',
* use that to set the token's text. Override this method to emit
* custom Token objects or provide a new factory.
*/
emit() {
const t = this.factory.create(
[this, this.input],
this.type,
this.#text,
this.channel,
this.tokenStartCharIndex,
this.getCharIndex() - 1,
this.currentTokenStartLine,
this.currentTokenColumn
);
this.emitToken(t);
return t;
}
emitEOF() {
const eof = this.factory.create(
[this, this.input],
Token.EOF,
void 0,
Token.DEFAULT_CHANNEL,
this.input.index,
this.input.index - 1,
this.line,
this.column
);
this.emitToken(eof);
return eof;
}
/** What is the index of the current character of lookahead? */
getCharIndex() {
return this.input.index;
}
/**
* Return a list of all Token objects in input char stream.
* Forces load of all tokens. Does not include EOF token.
*/
getAllTokens() {
const tokens = [];
let t = this.nextToken();
while (t.type !== Token.EOF) {
tokens.push(t);
t = this.nextToken();
}
return tokens;
}
notifyListeners(e) {
const start = this.tokenStartCharIndex;
const stop = this.input.index;
const text = this.input.getTextFromRange(start, stop);
const msg = "token recognition error at: '" + this.getErrorDisplay(text) + "'";
this.errorListenerDispatch.syntaxError(this, null, this.currentTokenStartLine, this.currentTokenColumn, msg, e);
}
getErrorDisplay(s) {
return s;
}
getErrorDisplayForChar(c) {
if (c.charCodeAt(0) === Token.EOF) {
return "<EOF>";
}
if (c === "\n") {
return "\\n";
}
if (c === " ") {
return "\\t";
}
if (c === "\r") {
return "\\r";
}
return c;
}
getCharErrorDisplay(c) {
return "'" + this.getErrorDisplayForChar(c) + "'";
}
/**
* Lexers can normally match any char in it's vocabulary after matching
* a token, so do the easy thing and just kill a character and hope
* it all works out. You can instead use the rule invocation stack
* to do sophisticated error recovery if you are in a fragment rule.
*/
recover(re) {
if (this.input.LA(1) !== Token.EOF) {
if (re instanceof LexerNoViableAltException) {
this.interpreter.consume(this.input);
} else {
this.input.consume();
}
}
}
get inputStream() {
return this.input;
}
set inputStream(input) {
this.reset(false);
this.input = input;
}
set tokenFactory(factory) {
this.factory = factory;
}
get tokenFactory() {
return this.factory;
}
get sourceName() {
return this.input.getSourceName();
}
get line() {
return this.interpreter.line;
}
set line(line) {
this.interpreter.line = line;
}
get column() {
return this.interpreter.column;
}
set column(column) {
this.interpreter.column = column;
}
get text() {
if (this.#text) {
return this.#text;
} else {
return this.interpreter.getText(this.input);
}
}
set text(text) {
this.#text = text;
}
};
// src/dfa/DFASerializer.ts
var DFASerializer = class {
static {
__name(this, "DFASerializer");
}
dfa;
vocabulary;
constructor(dfa, vocabulary) {
this.dfa = dfa;
this.vocabulary = vocabulary;
}
toString() {
if (!this.dfa.s0) {
return "";
}
let buf = "";
const states = this.dfa.getStates();
for (const s of states) {
let n2 = 0;
n2 = s.edges.length;
for (let i = 0; i < n2; i++) {
const t = s.edges[i];
if (t && t.stateNumber !== 2147483647) {
buf += this.getStateString(s);
const label = this.getEdgeLabel(i);
buf += "-";
buf += label;
buf += "->";
buf += this.getStateString(t);
buf += "\n";
}
}
}
return buf;
}
getEdgeLabel(i) {
const name = this.vocabulary.getDisplayName(i - 1);
return `${name}`;
}
getStateString(s) {
const n2 = s.stateNumber;
const baseStateStr = (s.isAcceptState ? ":" : "") + "s" + n2 + (s.requiresFullContext ? "^" : "");
if (s.isAcceptState) {
if (s.predicates !== null) {
return `${baseStateStr}=>${s.predicates.toString()}`;
}
return `${baseStateStr}=>${s.prediction}`;
} else {
return `${baseStateStr}`;
}
}
};
// src/utils/helpers.ts
var valueToString = /* @__PURE__ */ __name((v) => {
return v === null ? "null" : v;
}, "valueToString");
var arrayToString = /* @__PURE__ */ __name((value) => {
return Array.isArray(value) ? "[" + value.map(valueToString).join(", ") + "]" : "null";
}, "arrayToString");
var equalArrays = /* @__PURE__ */ __name((a, b) => {
if (a === b) {
return true;
}
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
const left = a[i];
const right = b[i];
if (left === right) {
continue;
}
if (!left || !left.equals(right)) {
return false;
}
}
return true;
}, "equalArrays");
var equalNumberArrays = /* @__PURE__ */ __name((a, b) => {
if (a === b) {
return true;
}
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}, "equalNumberArrays");
var escapeWhitespace = /* @__PURE__ */ __name((s, escapeSpaces = false) => {
s = s.replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r");
if (escapeSpaces) {
s = s.replace(/ /g, "\xB7");
}
return s;
}, "escapeWhitespace");
// src/dfa/DFAState.ts
var DFAState = class _DFAState {
static {
__name(this, "DFAState");
}
stateNumber = -1;
configs;
/**
* `edges[symbol]` points to target of symbol. Shift up by 1 so (-1) {@link Token.EOF} maps to `edges[0]`.
*/
edges = [];
isAcceptState = false;
/**
* If accept state, what ttype do we match or alt do we predict? This is set to {@link ATN.INVALID_ALT_NUMBER}
* when {@link predicates} `!= null` or {@link requiresFullContext}.
*/
prediction = -1;
lexerActionExecutor = null;
/**
* Indicates that this state was created during SLL prediction that discovered a conflict between the configurations
* in the state. Future {@link ParserATNSimulator.execATN} invocations immediately jumped doing
* full context prediction if this field is true.
*/
requiresFullContext = false;
/**
* During SLL parsing, this is a list of predicates associated with the ATN configurations of the DFA state.
* When we have predicates, {@link requiresFullContext} is `false` since full context prediction evaluates
* predicates on-the-fly. If this is not null, then {@link prediction} is `ATN.INVALID_ALT_NUMBER`.
*
* We only use these for non-{@link #requiresFullContext} but conflicting states. That
* means we know from the context (it's $ or we don't dip into outer
* context) that it's an ambiguity not a conflict.
*
* This list is computed by {@link ParserATNSimulator#predicateDFAState}.
*/
predicates = null;
constructor(configs) {
if (configs) {
this.configs = configs;
}
}
static fromState(stateNumber) {
const result = new _DFAState();
result.stateNumber = stateNumber;
return result;
}
static fromConfigs(configs) {
return new _DFAState(configs);
}
static hashCode(state) {
return state.configs.hashCode();
}
/**
* Two {@link DFAState} instances are equal if their ATN configuration sets
* are the same. This method is used to see if a state already exists.
*
* Because the number of alternatives and number of ATN configurations are
* finite, there is a finite number of DFA states that can be processed.
* This is necessary to show that the algorithm terminates.
*
* Cannot test the DFA state numbers here because in
* {@link ParserATNSimulator#addDFAState} we need to know if any other state
* exists that has this exact set of ATN configurations. The
* {@link #stateNumber} is irrelevant.
*
* @param a The first {@link DFAState}.
* @param b The second {@link DFAState}.
*
* @returns `true` if the two states are equal, otherwise `false`.
*/
static equals(a, b) {
return a.configs.equals(b.configs);
}
/**
* @returns the set of all alts mentioned by all ATN configurations in this DFA state.
*/
getAltSet() {
const alts = /* @__PURE__ */ new Set();
for (const config of this.configs) {
alts.add(config.alt);
}
if (alts.size === 0) {
return null;
}
return alts;
}
toString() {
let buf = "";
buf += this.stateNumber;
buf += ":";
buf += this.configs ? this.configs.toString() : "";
if (this.isAcceptState) {
buf += "=>";
if (this.predicates) {
buf += arrayToString(this.predicates);
} else {
buf += this.prediction;
}
}
return buf.toString();
}
};
// src/Vocabulary.ts
var Vocabulary = class _Vocabulary {
static {
__name(this, "Vocabulary");
}
static EMPTY_NAMES = [];
/**
* Gets an empty {@link Vocabulary} instance.
*
*
* No literal or symbol names are assigned to token types, so
* {@link #getDisplayName(int)} returns the numeric value for all tokens
* except {@link Token#EOF}.
*/
static EMPTY_VOCABULARY = new _Vocabulary(_Vocabulary.EMPTY_NAMES, _Vocabulary.EMPTY_NAMES, _Vocabulary.EMPTY_NAMES);
maxTokenType;
literalNames;
symbolicNames;
displayNames;
/**
* Constructs a new instance of {@link Vocabulary} from the specified
* literal, symbolic, and display token names.
*
* @param literalNames The literal names assigned to tokens, or `null`
* if no literal names are assigned.
* @param symbolicNames The symbolic names assigned to tokens, or
* `null` if no symbolic names are assigned.
* @param displayNames The display names assigned to tokens, or `null`
* to use the values in `literalNames` and `symbolicNames` as
* the source of display names, as described in
* {@link #getDisplayName(int)}.
*/
constructor(literalNames, symbolicNames, displayNames) {
this.literalNames = literalNames ?? _Vocabulary.EMPTY_NAMES;
this.symbolicNames = symbolicNames ?? _Vocabulary.EMPTY_NAMES;
this.displayNames = displayNames ?? _Vocabulary.EMPTY_NAMES;
this.maxTokenType = Math.max(this.displayNames.length, Math.max(
this.literalNames.length,
this.symbolicNames.length
)) - 1;
}
/**
* Returns a {@link Vocabulary} instance from the specified set of token
* names. This method acts as a compatibility layer for the single
* `tokenNames` array generated by previous releases of ANTLR.
*
* The resulting vocabulary instance returns `null` for
* {@link getLiteralName getLiteralName(int)} and {@link getSymbolicName getSymbolicName(int)}, and the
* value from `tokenNames` for the display names.
*
* @param tokenNames The token names, or `null` if no token names are
* available.
* @returns A {@link Vocabulary} instance which uses `tokenNames` for
* the display names of tokens.
*/
static fromTokenNames(tokenNames) {
if (tokenNames == null || tokenNames.length === 0) {
return _Vocabulary.EMPTY_VOCABULARY;
}
const literalNames = [...tokenNames];
const symbolicNames = [...tokenNames];
for (let i = 0; i < tokenNames.length; i++) {
const tokenName = tokenNames[i];
if (tokenName == null) {
continue;
}
if (tokenName.length > 0) {
const firstChar = tokenName.codePointAt(0);
if (firstChar === 39) {
symbolicNames[i] = null;
continue;
} else if (firstChar >= 65 && firstChar <= 90) {
literalNames[i] = null;
continue;
}
}
literalNames[i] = null;
symbolicNames[i] = null;
}
return new _Vocabulary(literalNames, symbolicNames, tokenNames);
}
getMaxTokenType() {
return this.maxTokenType;
}
getLiteralName(tokenType) {
if (tokenType >= 0 && tokenType < this.literalNames.length) {
return this.literalNames[tokenType];
}
return null;
}
getSymbolicName(tokenType) {
if (tokenType >= 0 && tokenType < this.symbolicNames.length) {
return this.symbolicNames[tokenType];
}
if (tokenType === Token.EOF) {
return "EOF";
}
return null;
}
getDisplayName(tokenType) {
if (tokenType >= 0 && tokenType < this.displayNames.length) {
const displayName = this.displayNames[tokenType];
if (displayName != null) {
return displayName;
}
}
const literalName = this.getLiteralName(tokenType);
if (literalName != null) {
return literalName;
}
const symbolicName = this.getSymbolicName(tokenType);
if (symbolicName != null) {
return symbolicName;
}
return `${tokenType}`;
}
getLiteralNames() {
return this.literalNames;
}
getSymbolicNames() {
return this.symbolicNames;
}
getDisplayNames() {
return this.displayNames;
}
};
// src/dfa/LexerDFASerializer.ts
var LexerDFASerializer = class extends DFASerializer {
static {
__name(this, "LexerDFASerializer");
}
constructor(dfa) {
super(dfa, Vocabulary.EMPTY_VOCABULARY);
}
getEdgeLabel = /* @__PURE__ */ __name((i) => {
return "'" + String.fromCharCode(i) + "'";
}, "getEdgeLabel");
};
// src/atn/ATNState.ts
var ATNState = class _ATNState {
static {
__name(this, "ATNState");
}
static INVALID_STATE_NUMBER = -1;
static INVALID_TYPE = 0;
static BASIC = 1;
static RULE_START = 2;
static BLOCK_START = 3;
static PLUS_BLOCK_START = 4;
static STAR_BLOCK_START = 5;
static TOKEN_START = 6;
static RULE_STOP = 7;
static BLOCK_END = 8;
static STAR_LOOP_BACK = 9;
static STAR_LOOP_ENTRY = 10;
static PLUS_LOOP_BACK = 11;
static LOOP_END = 12;
static stateType = _ATNState.INVALID_STATE_NUMBER;
stateNumber = 0;
ruleIndex = 0;
// at runtime, we don't have Rule objects
epsilonOnlyTransitions = false;
/** Used to cache lookahead during parsing, not used during construction */
nextTokenWithinRule;
/** Track the transitions emanating from this ATN state. */
transitions = [];
hashCode() {
return this.stateNumber;
}
equals(other) {
return this.stateNumber === other.stateNumber;
}
toString() {
return `${this.stateNumber}`;
}
addTransitionAtIndex(index, transition) {
if (this.transitions.length === 0) {
this.epsilonOnlyTransitions = transition.isEpsilon;
} else if (this.epsilonOnlyTransitions !== transition.isEpsilon) {
this.epsilonOnlyTransitions = false;
}
this.transitions.splice(index, 1, transition);
}
addTransition(transition) {
if (this.transitions.length === 0) {
this.epsilonOnlyTransitions = transition.isEpsilon;
} else if (this.epsilonOnlyTransitions !== transition.isEpsilon) {
this.epsilonOnlyTransitions = false;
}
this.transitions.push(transition);
}
setTransition(i, e) {
this.transitions.splice(i, 1, e);
}
removeTransition(index) {
const t = this.transitions.splice(index, 1);
return t[0];
}
};
// src/atn/DecisionState.ts
var DecisionState = class extends ATNState {
static {
__name(this, "DecisionState");
}
decision = -1;
nonGreedy = false;
};
// src/atn/StarLoopEntryState.ts
var StarLoopEntryState = class extends DecisionState {
static {
__name(this, "StarLoopEntryState");
}
static stateType = ATNState.STAR_LOOP_ENTRY;
// This is always set during ATN deserialization
loopBackState;
/**
* Indicates whether this state can benefit from a precedence DFA during SLL
* decision making.
*
* This is a computed property that is calculated during ATN deserialization
* and stored for use in {@link ParserATNSimulator} and
* {@link ParserInterpreter}.
*
* @see `DFA.isPrecedenceDfa`
*/
precedenceRuleDecision = false;
};
// src/dfa/DFA.ts
var DFA = class {
static {
__name(this, "DFA");
}
s0;
decision;
/** From which ATN state did we create this DFA? */
atnStartState;
/**
* Gets whether this DFA is a precedence DFA. Precedence DFAs use a special
* start state {@link #s0} which is not stored in {@link #states}. The
* {@link DFAState#edges} array for this start state contains outgoing edges
* supplying individual start states corresponding to specific precedence
* values.
*
* @returns `true` if this is a precedence DFA; otherwise, `false`.
*/
isPrecedenceDfa;
/**
* A mapping from an ATNConfigSet hash to a DFAState.
* Used to quick look up the DFA state for a particular configuration set.
*/
states = /* @__PURE__ */ new Map();
constructor(atnStartState, decision) {
this.atnStartState = atnStartState;
this.decision = decision ?? 0;
let precedenceDfa = false;
if (atnStartState instanceof StarLoopEntryState) {
if (atnStartState.precedenceRuleDecision) {
precedenceDfa = true;
this.s0 = DFAState.fromState(-1);
}
}
this.isPrecedenceDfa = precedenceDfa;
}
[Symbol.iterator] = () => {
return this.states.values()[Symbol.iterator]();
};
/**
* Get the start state for a specific precedence value.
*
* @param precedence The current precedence.
@returns The start state corresponding to the specified precedence, or
* `null` if no start state exists for the specified precedence.
*
* @throws IllegalStateException if this is not a precedence DFA.
* @see #isPrecedenceDfa
*/
getPrecedenceStartState = /* @__PURE__ */ __name((precedence) => {
if (!this.isPrecedenceDfa) {
throw new Error(`Only precedence DFAs may contain a precedence start state.`);
}
if (!this.s0 || !this.s0.edges || precedence < 0 || precedence >= this.s0.edges.length) {
return void 0;
}
return this.s0.edges[precedence];
}, "getPrecedenceStartState");
/**
* Set the start state for a specific precedence value.
*
* @param precedence The current precedence.
* @param startState The start state corresponding to the specified precedence.
*/
setPrecedenceStartState = /* @__PURE__ */ __name((precedence, startState) => {
if (!this.isPrecedenceDfa) {
throw new Error(`Only precedence DFAs may contain a precedence start state.`);
}
if (precedence < 0 || !this.s0) {
return;
}
this.s0.edges[precedence] = startState;
}, "setPrecedenceStartState");
/**
* @returns a list of all states in this DFA, ordered by state number.
*/
getStates() {
const result = [...this.states.values()];
result.sort((o1, o2) => {
return o1.stateNumber - o2.stateNumber;
});
return result;
}
getState(state) {
return this.states.get(state.configs.hashCode()) ?? null;
}
getStateForConfigs(configs) {
return this.states.get(configs.hashCode()) ?? null;
}
addState(state) {
const hash = state.configs.hashCode();
if (this.states.has(hash)) {
return;
}
this.states.set(hash, state);
state.stateNumber = this.states.size - 1;
}
toString(vocabulary) {
if (!vocabulary) {
return this.toString(Vocabulary.EMPTY_VOCABULARY);
}
if (!this.s0) {
return "";
}
const serializer = new DFASerializer(this, vocabulary);
return serializer.toString() ?? "";
}
toLexerString() {
if (!this.s0) {
return "";
}
const serializer = new LexerDFASerializer(this);
return serializer.toString() ?? "";
}
get length() {
return this.states.size;
}
};
// src/misc/BitSet.ts
var BitSet = class {
static {
__name(this, "BitSet");
}
data;
/**
* Creates a new bit set. All bits are initially `false`.
*
* @param data Optional initial data.
*/
constructor(data) {
if (data) {
this.data = new Uint32Array(data.map((value) => {
return value >>> 0;
}));
} else {
this.data = new Uint32Array(1);
}
}
/**
* @returns an iterator over all set bits.
*/
[Symbol.iterator]() {
const length = this.data.length;
let currentIndex = 0;
let currentWord = this.data[currentIndex];
const words = this.data;
return {
[Symbol.iterator]() {
return this;
},
next: /* @__PURE__ */ __name(() => {
while (currentIndex < length) {
if (currentWord !== 0) {
const t = currentWord & -currentWord;
const value = (currentIndex << 5) + this.bitCount(t - 1);
currentWord ^= t;
return { done: false, value };
} else {
currentIndex++;
if (currentIndex < length) {
currentWord = words[currentIndex];
}
}
}
return { done: true, value: void 0 };
}, "next")
};
}
/**
* Sets a single bit or all of the bits in this `BitSet` to `false`.
*
* @param index the index of the bit to be cleared, or undefined to clear all bits.
*/
clear(index) {
if (index === void 0) {
this.data = new Uint32Array();
} else {
this.resize(index);
this.data[index >>> 5] &= ~(1 << index);
}
}
/**
* Performs a logical **OR** of this bit set with the bit set argument. This bit set is modified so that a bit in it
* has the value `true` if and only if it either already had the value `true` or the corresponding bit in the bit
* set argument has the value `true`.
*
* @param set the bit set to be ORed with.
*/
or(set) {
const minCount = Math.min(this.data.length, set.data.length);
for (let k = 0; k < minCount; ++k) {
this.data[k] |= set.data[k];
}
if (this.data.length < set.data.length) {
this.resize((set.data.length << 5) - 1);
const c = set.data.length;
for (let k = minCount; k < c; ++k) {
this.data[k] = set.data[k];
}
}
}
/**
* Returns the value of the bit with the specified index. The value is `true` if the bit with the index `bitIndex`
* is currently set in this `BitSet`; otherwise, the result is `false`.
*
* @param index the bit index
*
* @returns the value of the bit with the specified index.
*/
get(index) {
if (index < 0) {
throw new RangeError("index cannot be negative");
}
const slot = index >>> 5;
if (slot >= this.data.length) {
return false;
}
return (this.data[slot] & 1 << index % 32) !== 0;
}
/**
* @returns the number of set bits.
*/
get length() {
let result = 0;
const c = this.data.length;
const w = this.data;
for (let i = 0; i < c; i++) {
result += this.bitCount(w[i]);
}
return result;
}
/**
* @returns an array with indices of set bits.
*/
values() {
const result = new Array(this.length);
let pos = 0;
const length = this.data.length;
for (let k = 0; k < length; ++k) {
let w = this.data[k];
while (w !== 0) {
const t = w & -w;
result[pos++] = (k << 5) + this.bitCount(t - 1);
w ^= t;
}
}
return result;
}
/**
* @returns the index of the first bit that is set to `true` that occurs on or after the specified starting index.
* If no such bit exists then undefined is returned.
*
* @param fromIndex the index to start checking from (inclusive)
*/
nextSetBit(fromIndex) {
if (fromIndex < 0) {
throw new RangeError("index cannot be negative");
}
for (const index of this) {
if (index >= fromIndex) {
return index;
}
}
return void 0;
}
/**
* Sets the bit at the specified index to `true`.
*
* @param index a bit index
*/
set(index) {
if (index < 0) {
throw new RangeError("index cannot be negative");
}
this.resize(index);
this.data[index >>> 5] |= 1 << index % 32;
}
/**
* @returns a string representation of this bit set.
*/
toString() {
return "{" + this.values().join(", ") + "}";
}
resize(index) {
const count = index + 32 >>> 5;
if (count <= this.data.length) {
return;
}
const data = new Uint32Array(count);
data.set(this.data);
data.fill(0, this.data.length);
this.data = data;
}
bitCount(v) {
v = v - (v >> 1 & 1431655765);
v = (v & 858993459) + (v >> 2 & 858993459);
v = v + (v >> 4) & 252645135;
v = v + (v >> 8);
v = v + (v >> 16);
return v & 63;
}
};
// src/utils/MurmurHash.ts
var c1 = 3432918353;
var c2 = 461845907;
var r1 = 15;
var r2 = 13;
var m = 5;
var n = 3864292196;
var MurmurHash = class _MurmurHash {
static {
__name(this, "MurmurHash");
}
static defaultSeed = 701;
constructor() {
}
/**
* Initialize the hash using the specified {@code seed}.
*
* @param seed the seed
*
* @returns the intermediate hash value
*/
static initialize(seed = _MurmurHash.defaultSeed) {
return seed;
}
static updateFromComparable(hash, value) {
return this.update(hash, value?.hashCode() ?? 0);
}
/**
* Update the intermediate hash value for the next input {@code value}.
*
* @param hash The intermediate hash value.
* @param value the value to add to the current hash.
*
* @returns the updated intermediate hash value
*/
static update(hash, value) {
value = Math.imul(value, c1);
value = value << r1 | value >>> 32 - r1;
value = Math.imul(value, c2);
hash = hash ^ value;
hash = hash << r2 | hash >>> 32 - r2;
hash = Math.imul(hash, m) + n;
return hash;
}
/**
* Apply the final computation steps to the intermediate value {@code hash}
* to form the final result of the MurmurHash 3 hash function.
*
* @param hash The intermediate hash value.
* @param entryCount The number of values added to the hash.
*
* @returns the final hash result
*/
static finish(hash, entryCount) {
hash ^= entryCount * 4;
hash ^= hash >>> 16;
hash = Math.imul(hash, 2246822507);
hash ^= hash >>> 13;
hash = Math.imul(hash, 3266489909);
hash ^= hash >>> 16;
return hash;
}
/**
* An all-in-one convenience method to compute a hash for a single value.
*
* @param value The value to hash.
* @param seed The seed for the hash value.
*
* @returns The computed hash.
*/
static hashCode(value, seed) {
return _MurmurHash.finish(_MurmurHash.update(seed ?? _MurmurHash.defaultSeed, value), 1);
}
};
// src/misc/ObjectEqualityComparator.ts
var ObjectEqualityComparator = class _ObjectEqualityComparator {
static {
__name(this, "ObjectEqualityComparator");
}
static instance = new _ObjectEqualityComparator();
hashCode(obj) {
if (obj == null) {
return 0;
}
return obj.hashCode();
}
equals(a, b) {
if (a == null) {
return b == null;
}
return a.equals(b);
}
};
// src/misc/DefaultEqualityComparator.ts
var DefaultEqualityComparator = class _DefaultEqualityComparator {
static {
__name(this, "DefaultEqualityComparator");
}
static instance = new _DefaultEqualityComparator();
hashCode(obj) {
if (obj == null) {
return 0;
}
return ObjectEqualityComparator.instance.hashCode(obj);
}
equals(a, b) {
if (a == null) {
return b == null;
}
if (typeof a === "string" || typeof a === "number") {
return a === b;
}
return ObjectEqualityComparator.instance.equals(a, b);
}
};
// src/misc/HashSet.ts
var HashSet = class _HashSet {
static {
__name(this, "HashSet");
}
static defaultLoadFactor = 0.75;
static initialCapacity = 16;
// must be power of 2
comparator;
buckets;
threshold;
/** How many elements in set */
itemCount = 0;
constructor(comparatorOrSet, initialCapacity = _HashSet.initialCapacity) {
if (comparatorOrSet instanceof _HashSet) {
this.comparator = comparatorOrSet.comparator;
this.buckets = comparatorOrSet.buckets.slice(0);
for (let i = 0; i < this.buckets.length; i++) {
const bucket = this.buckets[i];
if (bucket) {
this.buckets[i] = bucket.slice(0);
}
}
this.itemCount = comparatorOrSet.itemCount;
this.threshold = comparatorOrSet.threshold;
} else {
this.comparator = comparatorOrSet ?? DefaultEqualityComparator.instance;
this.buckets = this.createBuckets(initialCapacity);
this.threshold = Math.floor(_HashSet.initialCapacity * _HashSet.defaultLoadFactor);
}
}
/**
* Add `o` to set if not there; return existing value if already
* there. This method performs the same operation as {@link #add} aside from
* the return value.
*
* @param o the object to add to the set.
*
* @returns An existing element that equals to `o` if already in set, otherwise `o`.
*/
getOrAdd(o) {
if (this.itemCount > this.threshold) {
this.expand();
}
const b = this.getBucket(o);
let bucket = this.buckets[b];
if (!bucket) {
bucket = [o];
this.buckets[b] = bucket;
++this.itemCount;
return o;
}
for (const existing of bucket) {
if (this.comparator.equals(existing, o)) {
return existing;
}
}
bucket.push(o);
++this.itemCount;
return o;
}
get(o) {
if (o == null) {
return o;
}
const b = this.getBucket(o);
const bucket = this.buckets[b];
if (!bucket) {
return void 0;
}
for (const e of bucket) {
if (this.comparator.equals(e, o)) {
return e;
}
}
return void 0;
}
/**
* Removes the specified element from this set if it is present.
*
* @param o object to be removed from this set, if present.
*
* @returns `true` if the set contained the specified element.
*/
remove(o) {
if (o == null) {
return false;
}
const b = this.getBucket(o);
const bucket = this.buckets[b];
if (!bucket) {
return false;
}
for (let i = 0; i < bucket.length; i++) {
const existing = bucket[i];
if (this.comparator.equals(existing, o)) {
bucket.splice(i, 1);
--this.itemCount;
return true;
}
}
return false;
}
hashCode() {
let hash = MurmurHash.initialize();
for (const bucket of this.buckets) {
if (bucket == null) {
continue;
}
for (const o of bucket) {
if (o == null) {
break;
}
hash = MurmurHash.update(hash, this.comparator.hashCode(o));
}
}
hash = MurmurHash.finish(hash, this.size);
return hash;
}
equals(o) {
if (o === this) {
return true;
}
if (!(o instanceof _HashSet)) {
return false;
}
if (o.size !== this.size) {
return false;
}
return this.containsAll(o);
}
add(t) {
const existing = this.getOrAdd(t);
return existing === t;
}
contains(o) {
return this.containsFast(o);
}
containsFast(obj) {
if (obj == null) {
return false;
}
return this.get(obj) !== void 0;
}
*[Symbol.iterator]() {
yield* this.toArray();
}
toArray() {
const a = new Array(this.size);
let i = 0;
for (const bucket of this.buckets) {
if (bucket == null) {
continue;
}
for (const o of bucket) {
if (o == null) {
break;
}
a[i++] = o;
}
}
return a;
}
containsAll(collection) {
if (collection instanceof _HashSet) {
for (const bucket of collection.buckets) {
if (bucket == null) {
continue;
}
for (const o of bucket) {
if (o == null) {
break;
}
if (!this.containsFast(o)) {
return false;
}
}
}
} else {
for (const o of collection) {
if (!this.containsFast(o)) {
return false;
}
}
}
return true;
}
addAll(c) {
let changed = false;
for (const o of c) {
const existing = this.getOrAdd(o);
if (existing !== o) {
changed = true;
}
}
return changed;
}
clear() {
this.buckets = this.createBuckets(_HashSet.initialCapacity);
this.itemCount = 0;
this.threshold = Math.floor(_HashSet.initialCapacity * _HashSet.defaultLoadFactor);
}
toString() {
if (this.size === 0) {
return "{}";
}
let buf = "{";
let first = true;
for (const bucket of this.buckets) {
if (bucket == null) {
continue;
}
for (const o of bucket) {
if (o == null) {
break;
}
if (first) {
first = false;
} else {
buf += ", ";
}
buf += o.toString();
}
}
buf += "}";
return buf;
}
toTableString() {
let buf = "";
for (const bucket of this.buckets) {
if (bucket == null) {
buf += "null\n";
continue;
}
buf += "[";
let first = true;
for (const o of bucket) {
if (first) {
first = false;
} else {
buf += " ";
}
if (o == null) {
buf += "_";
} else {
buf += o.toString();
}
}
buf += "]\n";
}
return buf;
}
getBucket(o) {
const hash = this.comparator.hashCode(o);
const b = hash & this.buckets.length - 1;
return b;
}
expand() {
const old = this.buckets;
const newCapacity = this.buckets.length * 2;
const newTable = this.createBuckets(newCapacity);
this.buckets = newTable;
this.threshold = Math.floor(newCapacity * _HashSet.defaultLoadFactor);
for (const bucket of old) {
if (!bucket) {
continue;
}
for (const o of bucket) {
const b = this.getBucket(o);
let newBucket = this.buckets[b];
if (!newBucket) {
newBucket = [];
this.buckets[b] = newBucket;
}
newBucket.push(o);
}
}
}
get size() {
return this.itemCount;
}
get isEmpty() {
return this.itemCount === 0;
}
/**
* Return an array of `T[]` with length `capacity`.
*
* @param capacity the length of the array to return
* @returns the newly constructed array
*/
createBuckets(capacity) {
return new Array(capacity);
}
};
// src/misc/Interval.ts
var Interval = class _Interval {
static {
__name(this, "Interval");
}
static INVALID_INTERVAL = new _Interval(-1, -2);
static INTERVAL_POOL_MAX_VALUE = 1e3;
static cache = [];
start;
stop;
cachedHashCode;
constructor(start, stop) {
this.start = start;
this.stop = stop;
this.cachedHashCode = Math.imul(651 + start, 31) + stop;
}
/**
* Creates a new interval from the given values.
*
* Interval objects are used readonly so share all with the
* same single value a==b up to some max size. Use an array as a perfect hash.
* Return shared object for 0..INTERVAL_POOL_MAX_VALUE or a new
* Interval object with a..a in it. On Java.g4, 218623 IntervalSets
* have a..a (set with 1 element).
*
* @param a The start of the interval.
* @param b The end of the interval (inclusive).
*
* @returns A cached or new interval.
*/
static of(a, b) {
if (a !== b || a < 0 || a > _Interval.INTERVAL_POOL_MAX_VALUE) {
return new _Interval(a, b);
}
if (!_Interval.cache[a]) {
_Interval.cache[a] = new _Interval(a, a);
}
return _Interval.cache[a];
}
equals(o) {
return this.start === o.start && this.stop === o.stop;
}
hashCode() {
return this.cachedHashCode;
}
/** Does this start completely before other? Disjoint */
startsBeforeDisjoint(other) {
return this.start < other.start && this.stop < other.start;
}
/** Does this start at or before other? Nondisjoint */
startsBeforeNonDisjoint(other) {
return this.start <= other.start && this.stop >= other.start;
}
/** Does this.start start after other.stop? May or may not be disjoint */
startsAfter(other) {
return this.start > other.start;
}
/** Does this start completely after other? Disjoint */
startsAfterDisjoint(other) {
return this.start > other.stop;
}
/** Does this start after other? NonDisjoint */
startsAfterNonDisjoint(other) {
return this.start > other.start && this.start <= other.stop;
}
/** Are both ranges disjoint? I.e., no overlap? */
disjoint(other) {
return this.startsBeforeDisjoint(other) || this.startsAfterDisjoint(other);
}
/** Are two intervals adjacent such as 0..41 and 42..42? */
adjacent(other) {
return this.start === other.stop + 1 || this.stop === other.start - 1;
}
properlyContains(other) {
return other.start >= this.start && other.stop <= this.stop;
}
/** Return the interval computed from combining this and other */
union(other) {
return _Interval.of(Math.min(this.start, other.start), Math.max(this.stop, other.stop));
}
/** Return the interval in common between this and o */
intersection(other) {
return _Interval.of(Math.max(this.start, other.start), Math.min(this.stop, other.stop));
}
/**
* Return the interval with elements from this not in other;
* other must not be totally enclosed (properly contained)
* within this, which would result in two disjoint intervals
* instead of the single one returned by this method.
*/
differenceNotProperlyContained(other) {
let diff = null;
if (other.startsBeforeNonDisjoint(this)) {
diff = _Interval.of(Math.max(this.start, other.stop + 1), this.stop);
} else if (other.startsAfterNonDisjoint(this)) {
diff = _Interval.of(this.start, other.start - 1);
}
return diff;
}
toString() {
return `${this.start}..${this.stop}`;
}
get length() {
if (this.stop < this.start) {
return 0;
}
return this.stop - this.start + 1;
}
};
// src/misc/IntervalSet.ts
var IntervalSet = class _IntervalSet {
static {
__name(this, "IntervalSet");
}
/** The list of sorted, disjoint intervals. */
intervals = [];
cachedHashCode;
constructor(set) {
if (set) {
if (Array.isArray(set)) {
for (const el of set) {
this.addOne(el);
}
} else {
this.addSet(set);
}
}
}
/** Create a set with all ints within range [a..b] (inclusive) */
static of(a, b) {
const s = new _IntervalSet();
s.addRange(a, b);
return s;
}
/** Combine all sets in the array and return the union of them */
static or(sets) {
const result = new _IntervalSet();
for (const set of sets) {
result.addSet(set);
}
return result;
}
[Symbol.iterator]() {
return this.intervals[Symbol.iterator]();
}
get(index) {
return this.intervals[index];
}
/**
* Returns the minimum value contained in the set if not isNil().
*
* @returns the minimum value contained in the set.
*/
get minElement() {
if (this.intervals.length === 0) {
return Token.INVALID_TYPE;
}
return this.intervals[0].start;
}
/**
* Returns the maximum value contained in the set if not isNil().
*
* @returns the maximum value contained in the set.
*/
get maxElement() {
if (this.intervals.length === 0) {
return Token.INVALID_TYPE;
}
return this.intervals[this.intervals.length - 1].stop;
}
clear() {
this.cachedHashCode = void 0;
this.intervals = [];
}
/**
* Add a single element to the set. An isolated element is stored
* as a range el..el.
*/
addOne(v) {
this.addInterval(new Interval(v, v));
}
/**
* Add interval; i.e., add all integers from a to b to set.
* If b < a, do nothing.
* Keep list in sorted order (by left range value).
* If overlap, combine ranges. For example,
* If this is {1..5, 10..20}, adding 6..7 yields
* {1..5, 6..7, 10..20}. Adding 4..8 yields {1..8, 10..20}.
*/
addRange(l, h) {
this.addInterval(new Interval(l, h));
}
addInterval(addition) {
this.cachedHashCode = void 0;
if (this.intervals.length === 0) {
this.intervals.push(addition);
} else {
for (let pos = 0; pos < this.intervals.length; pos++) {
const existing = this.intervals[pos];
if (addition.equals(existing)) {
return;
}
if (addition.adjacent(existing) || !addition.disjoint(existing)) {
const bigger = addition.union(existing);
this.intervals[pos] = bigger;
for (let sub = pos + 1; sub < this.intervals.length; ) {
const next = this.intervals[sub];
if (!bigger.adjacent(next) && bigger.disjoint(next)) {
break;
}
this.intervals.splice(sub, 1);
this.intervals[pos] = bigger.union(next);
}
return;
}
if (addition.startsBeforeDisjoint(existing)) {
this.intervals.splice(pos, 0, addition);
return;
}
}
this.intervals.push(addition);
}
}
addSet(other) {
other.intervals.forEach((toAdd) => {
return this.addInterval(toAdd);
}, this);
return this;
}
complementWithVocabulary(vocabulary) {
const result = new _IntervalSet();
if (!vocabulary) {
return result;
}
if (vocabulary.length === 0) {
return result;
}
result.addSet(vocabulary);
return result.subtract(this);
}
complement(minElement, maxElement) {
const result = new _IntervalSet();
result.addInterval(new Interval(minElement, maxElement));
return result.subtract(this);
}
/** combine all sets in the array returned the or'd value */
or(sets) {
const result = new _IntervalSet();
result.addSet(this);
sets.forEach((set) => {
return result.addSet(set);
});
return result;
}
and(other) {
if (other.length === 0) {
return new _IntervalSet();
}
const myIntervals = this.intervals;
const theirIntervals = other.intervals;
let intersection;
const mySize = myIntervals.length;
const theirSize = theirIntervals.length;
let i = 0;
let j = 0;
while (i < mySize && j < theirSize) {
const mine = myIntervals[i];
const theirs = theirIntervals[j];
if (mine.startsBeforeDisjoint(theirs)) {
i++;
} else if (theirs.startsBeforeDisjoint(mine)) {
j++;
} else if (mine.properlyContains(theirs)) {
if (!intersection) {
intersection = new _IntervalSet();
}
intersection.addInterval(mine.intersection(theirs));
j++;
} else if (theirs.properlyContains(mine)) {
if (!intersection) {
intersection = new _IntervalSet();
}
intersection.addInterval(mine.intersection(theirs));
i++;
} else if (!mine.disjoint(theirs)) {
if (!intersection) {
intersection = new _IntervalSet();
}
intersection.addInterval(mine.intersection(theirs));
if (mine.startsAfterNonDisjoint(theirs)) {
j++;
} else if (theirs.startsAfterNonDisjoint(mine)) {
i++;
}
}
}
if (!intersection) {
return new _IntervalSet();
}
return intersection;
}
/**
* Compute the set difference between two interval sets. The specific
* operation is `left - right`. If either of the input sets is
* `null`, it is treated as though it was an empty set.
*/
subtract(other) {
if (this.length === 0) {
return new _IntervalSet();
}
const result = new _IntervalSet(this);
if (other.length === 0) {
return result;
}
let resultI = 0;
let rightI = 0;
while (resultI < result.intervals.length && rightI < other.intervals.length) {
const resultInterval = result.intervals[resultI];
const rightInterval = other.intervals[rightI];
if (rightInterval.stop < resultInterval.start) {
rightI++;
continue;
}
if (rightInterval.start > resultInterval.stop) {
resultI++;
continue;
}
let beforeCurrent;
let afterCurrent;
if (rightInterval.start > resultInterval.start) {
beforeCurrent = new Interval(resultInterval.start, rightInterval.start - 1);
}
if (rightInterval.stop < resultInterval.stop) {
afterCurrent = new Interval(rightInterval.stop + 1, resultInterval.stop);
}
if (beforeCurrent) {
if (afterCurrent) {
result.intervals[resultI] = beforeCurrent;
result.intervals.splice(resultI + 1, 0, afterCurrent);
resultI++;
rightI++;
} else {
result.intervals[resultI] = beforeCurrent;
resultI++;
}
} else {
if (afterCurrent) {
result.intervals[resultI] = afterCurrent;
rightI++;
} else {
result.intervals.splice(resultI, 1);
}
}
}
return result;
}
contains(el) {
const n2 = this.intervals.length;
let l = 0;
let r = n2 - 1;
while (l <= r) {
const m2 = Math.floor((l + r) / 2);
const interval = this.intervals[m2];
if (interval.stop < el) {
l = m2 + 1;
} else if (interval.start > el) {
r = m2 - 1;
} else {
return true;
}
}
return false;
}
removeRange(toRemove) {
this.cachedHashCode = void 0;
if (toRemove.start === toRemove.stop) {
this.removeOne(toRemove.start);
} else if (this.intervals !== null) {
let pos = 0;
for (const existing of this.intervals) {
if (toRemove.stop <= existing.start) {
return;
} else if (toRemove.start > existing.start && toRemove.stop < existing.stop) {
this.intervals[pos] = new Interval(existing.start, toRemove.start);
const x = new Interval(toRemove.stop, existing.stop);
this.intervals.splice(pos, 0, x);
return;
} else if (toRemove.start <= existing.start && toRemove.stop >= existing.stop) {
this.intervals.splice(pos, 1);
pos = pos - 1;
} else if (toRemove.start < existing.stop) {
this.intervals[pos] = new Interval(existing.start, toRemove.start);
} else if (toRemove.stop < existing.stop) {
this.intervals[pos] = new Interval(toRemove.stop, existing.stop);
}
pos += 1;
}
}
}
removeOne(value) {
this.cachedHashCode = void 0;
for (let i = 0; i < this.intervals.length; i++) {
const existing = this.intervals[i];
if (value < existing.start) {
return;
} else if (value === existing.start && value === existing.stop) {
this.intervals.splice(i, 1);
return;
} else if (value === existing.start) {
this.intervals[i] = new Interval(existing.start + 1, existing.stop);
return;
} else if (value === existing.stop) {
this.intervals[i] = new Interval(existing.start, existing.stop - 1);
return;
} else if (value < existing.stop) {
const replace = new Interval(existing.start, value - 1);
this.intervals[i] = new Interval(value + 1, existing.stop);
this.intervals.splice(i, 0, replace);
return;
}
}
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hash = MurmurHash.initialize();
for (const interval of this.intervals) {
hash = MurmurHash.update(hash, interval.start);
hash = MurmurHash.update(hash, interval.stop);
}
this.cachedHashCode = MurmurHash.finish(hash, this.intervals.length * 2);
}
return this.cachedHashCode;
}
/**
* Are two IntervalSets equal? Because all intervals are sorted and disjoint, equals is a simple linear walk over
* both lists to make sure they are the same. Interval.equals() is used by the List.equals() method to check
* the ranges.
*/
equals(other) {
if (this === other) {
return true;
}
if (this.intervals.length !== other.intervals.length) {
return false;
}
for (let i = 0; i < this.intervals.length; i++) {
if (!this.intervals[i].equals(other.intervals[i])) {
return false;
}
}
return true;
}
toString(elementsAreChar) {
if (this.intervals.length === 0) {
return "{}";
}
let result = "";
if (this.length > 1) {
result += "{";
}
for (let i = 0; i < this.intervals.length; ++i) {
const interval = this.intervals[i];
const start = interval.start;
const stop = interval.stop;
if (start === stop) {
if (start === Token.EOF) {
result += "<EOF>";
} else if (elementsAreChar) {
result += "'" + String.fromCodePoint(start) + "'";
} else {
result += start;
}
} else {
if (elementsAreChar) {
result += "'" + String.fromCodePoint(start) + "'..'" + String.fromCodePoint(stop) + "'";
} else {
result += start + ".." + stop;
}
}
if (i < this.intervals.length - 1) {
result += ", ";
}
}
if (this.length > 1) {
result += "}";
}
return result;
}
toStringWithVocabulary(vocabulary) {
if (this.intervals.length === 0) {
return "{}";
}
let result = "";
if (this.length > 1) {
result += "{";
}
for (let i = 0; i < this.intervals.length; ++i) {
const interval = this.intervals[i];
const start = interval.start;
const stop = interval.stop;
if (start === stop) {
if (start === Token.EOF) {
result += "<EOF>";
} else {
result += this.elementName(vocabulary, start);
}
} else {
for (let i2 = start; i2 <= stop; ++i2) {
if (i2 > start) {
result += ", ";
}
result += this.elementName(vocabulary, i2);
}
}
if (i < this.intervals.length - 1) {
result += ", ";
}
}
if (this.length > 1) {
result += "}";
}
return result;
}
toStringWithRuleNames(ruleNames) {
if (this.intervals.length === 0) {
return "{}";
}
let result = "";
if (this.length > 1) {
result += "{";
}
const vocabulary = Vocabulary.fromTokenNames(ruleNames);
for (let i = 0; i < this.intervals.length; ++i) {
const interval = this.intervals[i];
const start = interval.start;
const stop = interval.stop;
if (start === stop) {
if (start === Token.EOF) {
result += "<EOF>";
} else {
result += this.elementName(vocabulary, start);
}
} else {
for (let i2 = start; i2 <= stop; ++i2) {
if (i2 > start) {
result += ", ";
}
result += this.elementName(vocabulary, i2);
}
}
if (i < this.intervals.length - 1) {
result += ", ";
}
}
if (this.length > 1) {
result += "}";
}
return result;
}
toArray() {
const data = [];
for (const interval of this.intervals) {
for (let j = interval.start; j <= interval.stop; j++) {
data.push(j);
}
}
return data;
}
/** @returns the number of elements in this set. */
get length() {
let result = 0;
for (const interval of this.intervals) {
result += interval.length;
}
return result;
}
elementName(vocabulary, token) {
if (token === Token.EOF) {
return "<EOF>";
}
if (token === Token.EPSILON) {
return "<EPSILON>";
}
return vocabulary.getDisplayName(token);
}
};
// src/atn/SemanticContext.ts
var SemanticContext = class _SemanticContext {
static {
__name(this, "SemanticContext");
}
cachedHashCode;
static andContext(a, b) {
if (a === null || a === _SemanticContext.NONE) {
return b;
}
if (b === null || b === _SemanticContext.NONE) {
return a;
}
const result = new AND(a, b);
if (result.operands.length === 1) {
return result.operands[0];
}
return result;
}
static orContext(a, b) {
if (a === null) {
return b;
}
if (b === null) {
return a;
}
if (a === _SemanticContext.NONE || b === _SemanticContext.NONE) {
return _SemanticContext.NONE;
}
const result = new OR(a, b);
if (result.operands.length === 1) {
return result.operands[0];
} else {
return result;
}
}
static filterPrecedencePredicates(set) {
const result = [];
for (const context of set) {
if (context instanceof _SemanticContext.PrecedencePredicate) {
result.push(context);
}
}
return result;
}
/**
* Evaluate the precedence predicates for the context and reduce the result.
*
* @param _parser The parser instance.
* @param _parserCallStack The current parser context object.
* @returns The simplified semantic context after precedence predicates are
* evaluated, which will be one of the following values.
* - {@link NONE}: if the predicate simplifies to `true` after
* precedence predicates are evaluated.
* - `null`: if the predicate simplifies to `false` after
* precedence predicates are evaluated.
* - `this`: if the semantic context is not changed as a result of
* precedence predicate evaluation.
* - A non-`null` {@link SemanticContext}: the new simplified
* semantic context after precedence predicates are evaluated.
*/
evalPrecedence(_parser, _parserCallStack) {
return this;
}
};
var AND = class _AND extends SemanticContext {
static {
__name(this, "AND");
}
operands;
/**
* A semantic context which is true whenever none of the contained contexts
* is false
*/
constructor(a, b) {
super();
const operands = new HashSet();
if (a instanceof _AND) {
a.operands.forEach((o) => {
operands.add(o);
});
} else {
operands.add(a);
}
if (b instanceof _AND) {
b.operands.forEach((o) => {
operands.add(o);
});
} else {
operands.add(b);
}
const precedencePredicates = SemanticContext.filterPrecedencePredicates(operands);
if (precedencePredicates.length > 0) {
let reduced = null;
precedencePredicates.forEach((p) => {
if (reduced === null || p.precedence < reduced.precedence) {
reduced = p;
}
});
if (reduced) {
operands.add(reduced);
}
}
this.operands = operands.toArray();
}
equals(other) {
if (this === other) {
return true;
}
if (!(other instanceof _AND)) {
return false;
}
return equalArrays(this.operands, other.operands);
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hash = MurmurHash.initialize();
for (const operand of this.operands) {
hash = MurmurHash.updateFromComparable(hash, operand);
}
hash = MurmurHash.update(hash, 3813686060);
this.cachedHashCode = MurmurHash.finish(hash, this.operands.length + 1);
}
return this.cachedHashCode;
}
/**
* {@inheritDoc}
*
*
* The evaluation of predicates by this context is short-circuiting, but
* unordered.
*/
evaluate(parser, parserCallStack) {
for (const operand of this.operands) {
if (!operand.evaluate(parser, parserCallStack)) {
return false;
}
}
return true;
}
evalPrecedence(parser, parserCallStack) {
let differs = false;
const operands = [];
for (const context of this.operands) {
const evaluated = context.evalPrecedence(parser, parserCallStack);
differs ||= evaluated !== context;
if (evaluated === null) {
return null;
} else if (evaluated !== SemanticContext.NONE) {
operands.push(evaluated);
}
}
if (!differs) {
return this;
}
if (operands.length === 0) {
return SemanticContext.NONE;
}
let result = null;
operands.forEach((o) => {
result = result === null ? o : SemanticContext.andContext(result, o);
});
return result;
}
toString() {
const s = this.operands.map((o) => {
return o.toString();
});
return (s.length > 3 ? s.slice(3) : s).join("&&");
}
};
var OR = class _OR extends SemanticContext {
static {
__name(this, "OR");
}
operands;
/**
* A semantic context which is true whenever at least one of the contained
* contexts is true
*/
constructor(a, b) {
super();
const operands = new HashSet();
if (a instanceof _OR) {
a.operands.forEach((o) => {
operands.add(o);
});
} else {
operands.add(a);
}
if (b instanceof _OR) {
b.operands.forEach((o) => {
operands.add(o);
});
} else {
operands.add(b);
}
const precedencePredicates = SemanticContext.filterPrecedencePredicates(operands);
if (precedencePredicates.length > 0) {
const s = precedencePredicates.sort((a2, b2) => {
return a2.compareTo(b2);
});
const reduced = s[s.length - 1];
operands.add(reduced);
}
this.operands = operands.toArray();
}
equals(other) {
if (this === other) {
return true;
} else if (!(other instanceof _OR)) {
return false;
} else {
return equalArrays(this.operands, other.operands);
}
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hash = MurmurHash.initialize();
for (const operand of this.operands) {
hash = MurmurHash.updateFromComparable(hash, operand);
}
hash = MurmurHash.update(hash, 3383313031);
this.cachedHashCode = MurmurHash.finish(hash, this.operands.length + 1);
}
return this.cachedHashCode;
}
/**
* The evaluation of predicates by this context is short-circuiting, but unordered.
*/
evaluate(parser, parserCallStack) {
for (const operand of this.operands) {
if (operand.evaluate(parser, parserCallStack)) {
return true;
}
}
return false;
}
evalPrecedence(parser, parserCallStack) {
let differs = false;
const operands = [];
for (const context of this.operands) {
const evaluated = context.evalPrecedence(parser, parserCallStack);
differs ||= evaluated !== context;
if (evaluated === SemanticContext.NONE) {
return SemanticContext.NONE;
} else if (evaluated !== null) {
operands.push(evaluated);
}
}
if (!differs) {
return this;
}
if (operands.length === 0) {
return null;
}
let result = null;
operands.forEach((o) => {
result = result === null ? o : SemanticContext.orContext(result, o);
});
return result;
}
toString() {
const s = this.operands.map((o) => {
return o.toString();
});
return (s.length > 3 ? s.slice(3) : s).join("||");
}
};
((SemanticContext2) => {
class Predicate extends SemanticContext2 {
static {
__name(this, "Predicate");
}
ruleIndex;
predIndex;
isCtxDependent;
// e.g., $i ref in pred
constructor(ruleIndex, predIndex, isCtxDependent) {
super();
this.ruleIndex = ruleIndex ?? -1;
this.predIndex = predIndex ?? -1;
this.isCtxDependent = isCtxDependent ?? false;
}
evaluate(parser, outerContext) {
const localctx = this.isCtxDependent ? outerContext : null;
return parser.sempred(localctx, this.ruleIndex, this.predIndex);
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hashCode = MurmurHash.initialize();
hashCode = MurmurHash.update(hashCode, this.ruleIndex);
hashCode = MurmurHash.update(hashCode, this.predIndex);
hashCode = MurmurHash.update(hashCode, this.isCtxDependent ? 1 : 0);
hashCode = MurmurHash.finish(hashCode, 3);
this.cachedHashCode = hashCode;
}
return this.cachedHashCode;
}
equals(other) {
if (this === other) {
return true;
}
return this.ruleIndex === other.ruleIndex && this.predIndex === other.predIndex && this.isCtxDependent === other.isCtxDependent;
}
toString() {
return "{" + this.ruleIndex + ":" + this.predIndex + "}?";
}
}
SemanticContext2.Predicate = Predicate;
class PrecedencePredicate extends SemanticContext2 {
static {
__name(this, "PrecedencePredicate");
}
precedence;
constructor(precedence) {
super();
this.precedence = precedence ?? 0;
}
evaluate(parser, outerContext) {
return parser.precpred(outerContext, this.precedence);
}
evalPrecedence(parser, outerContext) {
if (parser.precpred(outerContext ?? null, this.precedence)) {
return SemanticContext2.NONE;
}
return null;
}
compareTo(other) {
return this.precedence - other.precedence;
}
hashCode() {
return 31 + this.precedence;
}
equals(other) {
if (this === other) {
return true;
}
return this.precedence === other.precedence;
}
toString() {
return "{" + this.precedence + ">=prec}?";
}
}
SemanticContext2.PrecedencePredicate = PrecedencePredicate;
SemanticContext2.NONE = new Predicate();
})(SemanticContext || (SemanticContext = {}));
// src/atn/ATNConfig.ts
var ATNConfig = class _ATNConfig {
static {
__name(this, "ATNConfig");
}
/** The ATN state associated with this configuration */
state;
/** What alt (or lexer rule) is predicted by this configuration */
alt;
/**
* We cannot execute predicates dependent upon local context unless
* we know for sure we are in the correct context. Because there is
* no way to do this efficiently, we simply cannot evaluate
* dependent predicates unless we are in the rule that initially
* invokes the ATN simulator.
*
* closure() tracks the depth of how far we dip into the outer context:
* depth > 0.
*/
reachesIntoOuterContext = false;
// Not used in hash code.
precedenceFilterSuppressed = false;
// Not used in hash code.
get semanticContext() {
return this.#semanticContext;
}
cachedHashCode;
// Shared with LexerATNConfig.
/**
* The syntactic context is a graph-structured stack node whose
* path(s) to the root is the rule invocation(s)
* chain used to arrive at the state. The semantic context is
* the tree of semantic predicates encountered before reaching
* an ATN state
*/
#context = null;
#semanticContext;
/** Never create config classes directly. Use the factory methods below. */
constructor(c, state, context, semanticContext) {
this.state = state;
this.alt = c.alt;
this.context = context;
this.#semanticContext = semanticContext ?? SemanticContext.NONE;
this.reachesIntoOuterContext = c.reachesIntoOuterContext;
if (c.precedenceFilterSuppressed !== void 0) {
this.precedenceFilterSuppressed = c.precedenceFilterSuppressed;
}
}
static duplicate(old, semanticContext) {
return new _ATNConfig(old, old.state, old.context, semanticContext ?? old.semanticContext);
}
static createWithContext(state, alt, context, semanticContext) {
return new _ATNConfig({ alt }, state, context, semanticContext);
}
static createWithConfig(state, config, context) {
return new _ATNConfig(config, state, context ?? config.context, config.semanticContext);
}
static createWithSemanticContext(state, c, semanticContext) {
return new _ATNConfig(c, state ?? c.state, c.context, semanticContext);
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hashCode = MurmurHash.initialize(7);
hashCode = MurmurHash.update(hashCode, this.state.stateNumber);
hashCode = MurmurHash.update(hashCode, this.alt);
hashCode = MurmurHash.updateFromComparable(hashCode, this.#context);
hashCode = MurmurHash.updateFromComparable(hashCode, this.semanticContext);
hashCode = MurmurHash.finish(hashCode, 4);
this.cachedHashCode = hashCode;
}
return this.cachedHashCode;
}
/**
* The stack of invoking states leading to the rule/states associated
* with this config. We track only those contexts pushed during
* execution of the ATN simulator.
*/
get context() {
return this.#context;
}
set context(context) {
this.#context = context;
this.cachedHashCode = void 0;
}
/**
* An ATN configuration is equal to another if both have
* the same state, they predict the same alternative, and
* syntactic/semantic contexts are the same.
*/
equals(other) {
if (this === other) {
return true;
}
return this.state.stateNumber === other.state.stateNumber && this.alt === other.alt && (this.context === null ? other.context === null : this.context.equals(other.context)) && this.semanticContext.equals(other.semanticContext) && this.precedenceFilterSuppressed === other.precedenceFilterSuppressed;
}
toString(_recog, showAlt = true) {
let alt = "";
if (showAlt) {
alt = "," + this.alt;
}
return "(" + this.state + alt + (this.context !== null ? ",[" + this.context.toString() + "]" : "") + (this.semanticContext !== SemanticContext.NONE ? "," + this.semanticContext.toString() : "") + (this.reachesIntoOuterContext ? ",up=" + this.reachesIntoOuterContext : "") + ")";
}
};
// src/atn/PredictionContext.ts
var PredictionContext = class _PredictionContext {
static {
__name(this, "PredictionContext");
}
/**
* Represents `$` in an array in full context mode, when `$`
* doesn't mean wildcard: `$ + x = [$,x]`. Here,
* `$` = {@link EMPTY_RETURN_STATE}.
*/
static EMPTY_RETURN_STATE = 2147483647;
static traceATNSimulator = false;
cachedHashCode;
constructor(cachedHashCode) {
this.cachedHashCode = cachedHashCode;
}
static calculateEmptyHashCode() {
let hash = MurmurHash.initialize(31);
hash = MurmurHash.finish(hash, 0);
return hash;
}
static calculateHashCodeSingle(parent, returnState) {
let hash = MurmurHash.initialize(31);
hash = MurmurHash.updateFromComparable(hash, parent);
hash = MurmurHash.update(hash, returnState);
hash = MurmurHash.finish(hash, 2);
return hash;
}
static calculateHashCodeList(parents, returnStates) {
let hash = MurmurHash.initialize(31);
for (const parent of parents) {
hash = MurmurHash.updateFromComparable(hash, parent);
}
for (const returnState of returnStates) {
hash = MurmurHash.update(hash, returnState);
}
hash = MurmurHash.finish(hash, 2 * parents.length);
return hash;
}
isEmpty() {
return false;
}
hasEmptyPath() {
return this.getReturnState(this.length - 1) === _PredictionContext.EMPTY_RETURN_STATE;
}
hashCode() {
return this.cachedHashCode;
}
toString(_recog) {
return "";
}
};
// src/atn/SingletonPredictionContext.ts
var SingletonPredictionContext = class _SingletonPredictionContext extends PredictionContext {
static {
__name(this, "SingletonPredictionContext");
}
parent;
returnState;
constructor(parent, returnState) {
super(
parent ? PredictionContext.calculateHashCodeSingle(parent, returnState) : PredictionContext.calculateEmptyHashCode()
);
this.parent = parent ?? null;
this.returnState = returnState;
}
getParent(_index) {
return this.parent;
}
getReturnState(_index) {
return this.returnState;
}
equals(other) {
if (this === other) {
return true;
}
if (!(other instanceof _SingletonPredictionContext)) {
return false;
}
if (this.hashCode() !== other.hashCode()) {
return false;
}
if (this.returnState !== other.returnState) {
return false;
}
if (this.parent == null) {
return other.parent == null;
}
return this.parent.equals(other.parent);
}
toString() {
const up = this.parent === null ? "" : this.parent.toString();
if (up.length === 0) {
if (this.returnState === PredictionContext.EMPTY_RETURN_STATE) {
return "$";
}
return "" + this.returnState;
} else {
return "" + this.returnState + " " + up;
}
}
get length() {
return 1;
}
};
// src/atn/EmptyPredictionContext.ts
var EmptyPredictionContext = class _EmptyPredictionContext extends SingletonPredictionContext {
static {
__name(this, "EmptyPredictionContext");
}
/**
* Represents `$` in local context prediction, which means wildcard.
* `*+x = *`.
*/
static instance = new _EmptyPredictionContext();
constructor() {
super(void 0, PredictionContext.EMPTY_RETURN_STATE);
}
isEmpty() {
return true;
}
getParent() {
return null;
}
getReturnState() {
return this.returnState;
}
equals(other) {
return this === other;
}
toString() {
return "$";
}
};
// src/atn/Transition.ts
var Transition = class {
static {
__name(this, "Transition");
}
static INVALID = 0;
static EPSILON = 1;
static RANGE = 2;
static RULE = 3;
static PREDICATE = 4;
// e.g., {isType(input.LT(1))}
static ATOM = 5;
static ACTION = 6;
static SET = 7;
// ~(A|B) or ~atom, wildcard, which convert to next
static NOT_SET = 8;
static WILDCARD = 9;
static PRECEDENCE = 10;
/** The target of this transition. */
target;
constructor(target) {
this.target = target;
}
/**
* Determines if the transition is an "epsilon" transition.
*
* The default implementation returns `false`.
*
* @returns `true` if traversing this transition in the ATN does not
* consume an input symbol; otherwise, `false` if traversing this
* transition consumes (matches) an input symbol.
*/
get isEpsilon() {
return false;
}
get label() {
return null;
}
toString() {
return "";
}
};
// src/atn/SetTransition.ts
var SetTransition = class extends Transition {
static {
__name(this, "SetTransition");
}
set;
constructor(target, set) {
super(target);
if (set) {
this.set = set;
} else {
this.set = IntervalSet.of(Token.INVALID_TYPE, Token.INVALID_TYPE);
}
}
get transitionType() {
return Transition.SET;
}
get label() {
return this.set;
}
matches(symbol, _minVocabSymbol, _maxVocabSymbol) {
return this.set.contains(symbol);
}
toString() {
return this.set.toString();
}
};
// src/atn/NotSetTransition.ts
var NotSetTransition = class extends SetTransition {
static {
__name(this, "NotSetTransition");
}
get transitionType() {
return Transition.NOT_SET;
}
matches(symbol, minVocabSymbol, maxVocabSymbol) {
return symbol >= minVocabSymbol && symbol <= maxVocabSymbol && !super.matches(symbol, minVocabSymbol, maxVocabSymbol);
}
toString() {
return "~" + super.toString();
}
};
// src/misc/MapKeyEqualityOperator.ts
var MapKeyEqualityComparator = class {
static {
__name(this, "MapKeyEqualityComparator");
}
keyComparator;
constructor(keyComparator) {
this.keyComparator = keyComparator;
}
hashCode(obj) {
return this.keyComparator.hashCode(obj.key);
}
equals(a, b) {
return this.keyComparator.equals(a.key, b.key);
}
};
// src/misc/HashMap.ts
var HashMap = class _HashMap {
static {
__name(this, "HashMap");
}
backingStore;
constructor(keyComparer) {
if (keyComparer instanceof _HashMap) {
this.backingStore = new HashSet(keyComparer.backingStore);
} else {
keyComparer = keyComparer ?? DefaultEqualityComparator.instance;
this.backingStore = new HashSet(new MapKeyEqualityComparator(keyComparer));
}
}
clear() {
this.backingStore.clear();
}
containsKey(key) {
return this.backingStore.contains({ key });
}
get(key) {
const bucket = this.backingStore.get({ key });
if (!bucket) {
return void 0;
}
return bucket.value;
}
get isEmpty() {
return this.backingStore.isEmpty;
}
/**
* Sets the value for a key in the map. If the key is not present in the map, it is added.
* If the key is present, the value is updated and the old value is returned.
*
* @param key The key to set.
* @param value The value to set.
*
* @returns The old value for the key, if present.
*/
set(key, value) {
const element = this.backingStore.get({ key, value });
let result;
if (!element) {
this.backingStore.add({ key, value });
} else {
result = element.value;
element.value = value;
}
return result;
}
/**
* Sets the value for a key in the map if the key is not already present. Otherwise the value is not changed and
* the old value is returned.
*
* @param key The key to set.
* @param value The value to set.
*
* @returns The current value for the key, if present.
*/
setIfAbsent(key, value) {
const element = this.backingStore.get({ key, value });
let result;
if (!element) {
this.backingStore.add({ key, value });
} else {
result = element.value;
}
return result;
}
keys() {
return this.backingStore.toArray().map((bucket) => {
return bucket.key;
});
}
values() {
return this.backingStore.toArray().map((bucket) => {
return bucket.value;
});
}
get size() {
return this.backingStore.size;
}
hashCode() {
return this.backingStore.hashCode();
}
equals(o) {
return this.backingStore.equals(o.backingStore);
}
};
// src/tree/TerminalNode.ts
var TerminalNode = class {
static {
__name(this, "TerminalNode");
}
parent = null;
symbol;
constructor(symbol) {
this.symbol = symbol;
}
getChild(_i) {
return null;
}
getSymbol() {
return this.symbol;
}
getPayload() {
return this.symbol;
}
getSourceInterval() {
if (this.symbol === null) {
return Interval.INVALID_INTERVAL;
}
const tokenIndex = this.symbol.tokenIndex;
return new Interval(tokenIndex, tokenIndex);
}
getChildCount() {
return 0;
}
accept(visitor) {
return visitor.visitTerminal(this);
}
getText() {
return this.symbol?.text ?? "";
}
toString() {
if (this.symbol?.type === Token.EOF) {
return "<EOF>";
} else {
return this.symbol?.text ?? "";
}
}
toStringTree() {
return this.toString();
}
};
// src/tree/ErrorNode.ts
var ErrorNode = class extends TerminalNode {
static {
__name(this, "ErrorNode");
}
accept(visitor) {
return visitor.visitErrorNode(this);
}
};
// src/tree/Trees.ts
var Trees = class _Trees {
static {
__name(this, "Trees");
}
/**
* Print out a whole tree in LISP form. {@link getNodeText} is used on the
* node payloads to get the text for the nodes. Detect
* parse trees and extract data appropriately.
*/
static toStringTree(tree, ruleNames, recog) {
ruleNames = ruleNames ?? null;
if (recog) {
ruleNames = recog.ruleNames;
}
let s = _Trees.getNodeText(tree, ruleNames);
s = escapeWhitespace(s, false);
const c = tree.getChildCount();
if (c === 0) {
return s;
}
let res = "(" + s + " ";
if (c > 0) {
s = _Trees.toStringTree(tree.getChild(0), ruleNames);
res = res.concat(s);
}
for (let i = 1; i < c; i++) {
s = _Trees.toStringTree(tree.getChild(i), ruleNames);
res = res.concat(" " + s);
}
res = res.concat(")");
return res;
}
static getNodeText(t, ruleNames, recog) {
ruleNames = ruleNames ?? null;
if (recog) {
ruleNames = recog.ruleNames;
}
if (ruleNames !== null) {
if (t instanceof ParserRuleContext) {
const context = t.ruleContext;
const altNumber = context.getAltNumber();
if (altNumber !== 0) {
return ruleNames[t.ruleIndex] + ":" + altNumber;
}
return ruleNames[t.ruleIndex];
} else if (t instanceof ErrorNode) {
return t.toString();
} else if (t instanceof TerminalNode) {
return t.symbol.text;
}
}
const payload = t.getPayload();
if (isToken(payload)) {
return payload.text;
}
return String(t.getPayload());
}
/**
* Return ordered list of all children of this node
*/
static getChildren(t) {
const list = [];
for (let i = 0; i < t.getChildCount(); i++) {
list.push(t.getChild(i));
}
return list;
}
/**
* Return a list of all ancestors of this node. The first node of
* list is the root and the last is the parent of this node.
*/
static getAncestors(t) {
if (t.parent === null) {
return [];
}
let ancestors = [];
let p = t.parent;
while (p !== null) {
ancestors = [p].concat(ancestors);
p = p.parent;
}
return ancestors;
}
/**
* Return true if t is u's parent or a node on path to root from u.
*/
static isAncestorOf(t, u) {
if (t === null || u === null || t.parent === null) {
return false;
}
let p = u.parent;
while (p !== null) {
if (t === p) {
return true;
}
p = p.parent;
}
return false;
}
static findAllTokenNodes(t, ttype) {
return _Trees.findAllNodes(t, ttype, true);
}
static findAllRuleNodes(t, ruleIndex) {
return _Trees.findAllNodes(t, ruleIndex, false);
}
static findAllNodes(t, index, findTokens) {
const nodes = [];
_Trees.doFindAllNodes(t, index, findTokens, nodes);
return nodes;
}
static descendants(t) {
let nodes = [t];
for (let i = 0; i < t.getChildCount(); i++) {
nodes = nodes.concat(_Trees.descendants(t.getChild(i)));
}
return nodes;
}
/**
* Find smallest subtree of t enclosing range startTokenIndex..stopTokenIndex
* inclusively using post order traversal. Recursive depth-first-search.
*/
static getRootOfSubtreeEnclosingRegion(t, startTokenIndex, stopTokenIndex) {
const n2 = t.getChildCount();
for (let i = 0; i < n2; i++) {
const child = t.getChild(i);
const r = this.getRootOfSubtreeEnclosingRegion(child, startTokenIndex, stopTokenIndex);
if (r !== null) {
return r;
}
}
if (t instanceof ParserRuleContext) {
if (startTokenIndex >= t.start.tokenIndex && // is range fully contained in t?
(t.stop === null || stopTokenIndex <= t.stop.tokenIndex)) {
return t;
}
}
return null;
}
/**
* Replace any subtree siblings of root that are completely to left
* or right of lookahead range with a CommonToken(Token.INVALID_TYPE,"...")
* node. The source interval for t is not altered to suit smaller range!
*
* WARNING: destructive to t.
*/
static stripChildrenOutOfRange(t, root, startIndex, stopIndex) {
if (t === null) {
return;
}
for (let i = 0; i < t.getChildCount(); i++) {
const child = t.getChild(i);
const range = child.getSourceInterval();
if (t instanceof ParserRuleContext && (range.stop < startIndex || range.start > stopIndex)) {
if (this.isAncestorOf(child, root)) {
const abbrev = CommonToken.fromType(Token.INVALID_TYPE, "...");
t.children[i] = new TerminalNode(abbrev);
}
}
}
}
static doFindAllNodes(t, index, findTokens, nodes) {
if (findTokens && t instanceof TerminalNode) {
if (t.symbol?.type === index) {
nodes.push(t);
}
} else if (!findTokens && t instanceof ParserRuleContext) {
if (t.ruleIndex === index) {
nodes.push(t);
}
}
for (let i = 0; i < t.getChildCount(); i++) {
_Trees.doFindAllNodes(t.getChild(i), index, findTokens, nodes);
}
}
};
// src/ParserRuleContext.ts
var ParserRuleContext = class _ParserRuleContext {
static {
__name(this, "ParserRuleContext");
}
static empty = new _ParserRuleContext(null);
start = null;
stop = null;
children = [];
/**
* What state invoked the rule associated with this context?
* The "return address" is the followState of invokingState
* If parent is null, this should be -1 this context object represents
* the start rule.
*/
invokingState;
parent;
/**
* A rule context is a record of a single rule invocation. It knows
* which context invoked it, if any. If there is no parent context, then
* naturally the invoking state is not valid. The parent link
* provides a chain upwards from the current rule invocation to the root
* of the invocation tree, forming a stack. We actually carry no
* information about the rule associated with this context (except
* when parsing). We keep only the state number of the invoking state from
* the ATN submachine that invoked this. Contrast this with the s
* pointer inside ParserRuleContext that tracks the current state
* being "executed" for the current rule.
*
* The parent contexts are useful for computing lookahead sets and
* getting error information.
*
* These objects are used during parsing and prediction.
* For the special case of parsers, we use the subclass
* ParserRuleContext.
*/
constructor(parent, invokingStateNumber = -1) {
this.parent = parent;
this.invokingState = invokingStateNumber;
}
/** Copy a context */
copyFrom(ctx) {
this.parent = ctx.parent;
this.invokingState = ctx.invokingState;
this.children.slice(0, this.children.length);
this.start = ctx.start;
this.stop = ctx.stop;
if (ctx.children) {
ctx.children.forEach((child) => {
if (child instanceof ErrorNode) {
this.children.push(child);
child.parent = this;
}
});
}
}
// Double dispatch methods for listeners
enterRule(_listener) {
}
exitRule(_listener) {
}
addChild(child) {
this.children.push(child);
return child;
}
/**
* Used by enterOuterAlt to toss out a RuleContext previously added as
* we entered a rule. If we have label, we will need to remove
* generic ruleContext object.
*/
removeLastChild() {
this.children.pop();
}
addTokenNode(token) {
const node = new TerminalNode(token);
this.children.push(node);
node.parent = this;
return node;
}
addErrorNode(errorNode) {
errorNode.parent = this;
this.children.push(errorNode);
return errorNode;
}
getChild(i, type) {
if (i < 0 || i >= this.children.length) {
return null;
}
if (!type) {
return this.children[i];
}
for (const child of this.children) {
if (child instanceof type) {
if (i === 0) {
return child;
} else {
i -= 1;
}
}
}
return null;
}
getToken(ttype, i) {
if (i < 0 || i >= this.children.length) {
return null;
}
for (const child of this.children) {
if ("symbol" in child) {
if (child.symbol?.type === ttype) {
if (i === 0) {
return child;
} else {
i -= 1;
}
}
}
}
return null;
}
getTokens(ttype) {
const tokens = [];
for (const child of this.children) {
if ("symbol" in child) {
if (child.symbol?.type === ttype) {
tokens.push(child);
}
}
}
return tokens;
}
// XXX: base the child type selection on the rule index, not the class.
getRuleContext(index, ctxType) {
return this.getChild(index, ctxType);
}
// XXX: base the child type selection on the rule index, not the class.
getRuleContexts(ctxType) {
const contexts = [];
for (const child of this.children) {
if (child instanceof ctxType) {
contexts.push(child);
}
}
return contexts;
}
getChildCount() {
return this.children.length;
}
getSourceInterval() {
if (this.start === null) {
return Interval.INVALID_INTERVAL;
}
if (this.stop === null || this.stop.tokenIndex < this.start.tokenIndex) {
return new Interval(this.start.tokenIndex, this.start.tokenIndex - 1);
}
return new Interval(this.start.tokenIndex, this.stop.tokenIndex);
}
depth() {
let n2 = 0;
let p = this;
while (p !== null) {
p = p.parent;
n2 += 1;
}
return n2;
}
/**
* A context is empty if there is no invoking state; meaning nobody call
* current context.
*/
isEmpty() {
return this.invokingState === -1;
}
get ruleContext() {
return this;
}
get ruleIndex() {
return -1;
}
getPayload() {
return this;
}
getText() {
if (this.children.length === 0) {
return "";
}
return this.children.map((child) => {
return child.getText();
}).join("");
}
/**
* For rule associated with this parse tree internal node, return
* the outer alternative number used to match the input. Default
* implementation does not compute nor store this alt num. Create
* a subclass of ParserRuleContext with backing field and set
* option contextSuperClass.
* to set it.
*/
getAltNumber() {
return ATN.INVALID_ALT_NUMBER;
}
/**
* Set the outer alternative number for this context node. Default
* implementation does nothing to avoid backing field overhead for
* trees that don't need it. Create
* a subclass of ParserRuleContext with backing field and set
* option contextSuperClass.
*/
setAltNumber(_altNumber) {
}
accept(visitor) {
return visitor.visitChildren(this);
}
toStringTree(...args) {
if (args.length < 2) {
return Trees.toStringTree(this, null, args[0]);
}
return Trees.toStringTree(this, args[0], args[1]);
}
toString(ruleNames, stop) {
ruleNames = ruleNames ?? null;
stop = stop ?? null;
let p = this;
let s = "[";
while (p !== null && p !== stop) {
if (ruleNames === null) {
if (!p.isEmpty()) {
s += p.invokingState;
}
} else {
const ri = p.ruleIndex;
const ruleName = ri >= 0 && ri < ruleNames.length ? ruleNames[ri] : "" + ri;
s += ruleName;
}
if (p.parent !== null && (ruleNames !== null || !p.parent.isEmpty())) {
s += " ";
}
p = p.parent;
}
s += "]";
return s;
}
};
// src/atn/ArrayPredictionContext.ts
var ArrayPredictionContext = class _ArrayPredictionContext extends PredictionContext {
static {
__name(this, "ArrayPredictionContext");
}
parents = [];
returnStates = [];
constructor(parents, returnStates) {
super(PredictionContext.calculateHashCodeList(parents, returnStates));
this.parents = parents;
this.returnStates = returnStates;
return this;
}
isEmpty() {
return this.returnStates[0] === PredictionContext.EMPTY_RETURN_STATE;
}
get length() {
return this.returnStates.length;
}
getParent(index) {
return this.parents[index];
}
getReturnState(index) {
return this.returnStates[index];
}
equals(other) {
if (this === other) {
return true;
}
if (!(other instanceof _ArrayPredictionContext) || this.hashCode() !== other.hashCode()) {
return false;
}
return equalNumberArrays(this.returnStates, other.returnStates) && equalArrays(this.parents, other.parents);
}
toString() {
if (this.isEmpty()) {
return "[]";
}
const entries = [];
for (let i = 0; i < this.returnStates.length; i++) {
if (this.returnStates[i] === PredictionContext.EMPTY_RETURN_STATE) {
entries.push("$");
continue;
}
entries.push(this.returnStates[i].toString());
if (this.parents[i]) {
entries.push(this.parents[i].toString());
} else {
entries.push("null");
}
}
return `[${entries.join(", ")}]`;
}
};
// src/atn/helpers.ts
var createSingletonPredictionContext = /* @__PURE__ */ __name((parent, returnState) => {
if (returnState === PredictionContext.EMPTY_RETURN_STATE && parent === null) {
return EmptyPredictionContext.instance;
} else {
return new SingletonPredictionContext(parent, returnState);
}
}, "createSingletonPredictionContext");
// src/atn/PredictionContextUtils.ts
var predictionContextFromRuleContext = /* @__PURE__ */ __name((atn, outerContext) => {
if (!outerContext) {
outerContext = ParserRuleContext.empty;
}
if (!outerContext.parent || outerContext === ParserRuleContext.empty) {
return EmptyPredictionContext.instance;
}
const parent = predictionContextFromRuleContext(atn, outerContext.parent);
const state = atn.states[outerContext.invokingState];
const transition = state.transitions[0];
return createSingletonPredictionContext(parent, transition.followState.stateNumber);
}, "predictionContextFromRuleContext");
var getCachedPredictionContext = /* @__PURE__ */ __name((context, contextCache, visited) => {
if (context.isEmpty()) {
return context;
}
let existing = visited.get(context);
if (existing) {
return existing;
}
existing = contextCache.get(context);
if (existing) {
visited.set(context, existing);
return existing;
}
let changed = false;
let parents = [];
for (let i = 0; i < parents.length; i++) {
const parent = getCachedPredictionContext(context.getParent(i), contextCache, visited);
if (changed || parent !== context.getParent(i)) {
if (!changed) {
parents = [];
for (let j = 0; j < context.length; j++) {
parents[j] = context.getParent(j);
}
changed = true;
}
parents[i] = parent;
}
}
if (!changed) {
contextCache.add(context);
visited.set(context, context);
return context;
}
let updated;
if (parents.length === 0) {
updated = EmptyPredictionContext.instance;
} else if (parents.length === 1) {
updated = createSingletonPredictionContext(parents[0] ?? void 0, context.getReturnState(0));
} else {
updated = new ArrayPredictionContext(parents, context.returnStates);
}
contextCache.add(updated);
visited.set(updated, updated);
visited.set(context, updated);
return updated;
}, "getCachedPredictionContext");
var merge = /* @__PURE__ */ __name((a, b, rootIsWildcard, mergeCache) => {
if (a === b || a.equals(b)) {
return a;
}
if (a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) {
return mergeSingletons(a, b, rootIsWildcard, mergeCache);
}
if (rootIsWildcard) {
if (a instanceof EmptyPredictionContext) {
return a;
}
if (b instanceof EmptyPredictionContext) {
return b;
}
}
if (a instanceof SingletonPredictionContext) {
a = new ArrayPredictionContext([a.parent], [a.returnState]);
}
if (b instanceof SingletonPredictionContext) {
b = new ArrayPredictionContext([b.parent], [b.returnState]);
}
return mergeArrays(a, b, rootIsWildcard, mergeCache);
}, "merge");
var mergeArrays = /* @__PURE__ */ __name((a, b, rootIsWildcard, mergeCache) => {
if (mergeCache) {
let previous = mergeCache.get(a, b);
if (previous) {
return previous;
}
previous = mergeCache.get(b, a);
if (previous) {
return previous;
}
}
let i = 0;
let j = 0;
let k = 0;
let mergedReturnStates = new Array(a.returnStates.length + b.returnStates.length).fill(0);
let mergedParents = new Array(a.returnStates.length + b.returnStates.length).fill(null);
while (i < a.returnStates.length && j < b.returnStates.length) {
const aParent = a.parents[i];
const bParent = b.parents[j];
if (a.returnStates[i] === b.returnStates[j]) {
const payload = a.returnStates[i];
const bothDollars = payload === PredictionContext.EMPTY_RETURN_STATE && aParent === null && bParent === null;
const axAx = aParent !== null && bParent !== null && aParent === bParent;
if (bothDollars || axAx) {
mergedParents[k] = aParent;
mergedReturnStates[k] = payload;
} else {
mergedParents[k] = merge(aParent, bParent, rootIsWildcard, mergeCache);
mergedReturnStates[k] = payload;
}
i += 1;
j += 1;
} else if (a.returnStates[i] < b.returnStates[j]) {
mergedParents[k] = aParent;
mergedReturnStates[k] = a.returnStates[i];
i += 1;
} else {
mergedParents[k] = bParent;
mergedReturnStates[k] = b.returnStates[j];
j += 1;
}
k += 1;
}
if (i < a.returnStates.length) {
for (let p = i; p < a.returnStates.length; p++) {
mergedParents[k] = a.parents[p];
mergedReturnStates[k] = a.returnStates[p];
k += 1;
}
} else {
for (let p = j; p < b.returnStates.length; p++) {
mergedParents[k] = b.parents[p];
mergedReturnStates[k] = b.returnStates[p];
k += 1;
}
}
if (k < mergedParents.length) {
if (k === 1) {
const aNew = createSingletonPredictionContext(mergedParents[0] ?? void 0, mergedReturnStates[0]);
if (mergeCache !== null) {
mergeCache.set(a, b, aNew);
}
return aNew;
}
mergedParents = mergedParents.slice(0, k);
mergedReturnStates = mergedReturnStates.slice(0, k);
}
const merged = new ArrayPredictionContext(mergedParents, mergedReturnStates);
if (merged.equals(a)) {
if (mergeCache !== null) {
mergeCache.set(a, b, a);
}
if (PredictionContext.traceATNSimulator) {
console.log("mergeArrays a=" + a + ",b=" + b + " -> a");
}
return a;
}
if (merged.equals(b)) {
if (mergeCache !== null) {
mergeCache.set(a, b, b);
}
return b;
}
combineCommonParents(mergedParents);
if (mergeCache !== null) {
mergeCache.set(a, b, merged);
}
if (PredictionContext.traceATNSimulator) {
console.log("mergeArrays a=" + a + ",b=" + b + " -> " + merged);
}
return merged;
}, "mergeArrays");
var combineCommonParents = /* @__PURE__ */ __name((parents) => {
const uniqueParents = new HashMap(ObjectEqualityComparator.instance);
for (const parent of parents) {
if (parent) {
if (!uniqueParents.containsKey(parent)) {
uniqueParents.set(parent, parent);
}
}
}
for (let q = 0; q < parents.length; q++) {
if (parents[q]) {
parents[q] = uniqueParents.get(parents[q]) ?? null;
}
}
}, "combineCommonParents");
var mergeSingletons = /* @__PURE__ */ __name((a, b, rootIsWildcard, mergeCache) => {
if (mergeCache !== null) {
let previous = mergeCache.get(a, b);
if (previous !== null) {
return previous;
}
previous = mergeCache.get(b, a);
if (previous !== null) {
return previous;
}
}
const rootMerge = mergeRoot(a, b, rootIsWildcard);
if (rootMerge !== null) {
if (mergeCache !== null) {
mergeCache.set(a, b, rootMerge);
}
return rootMerge;
}
if (a.returnState === b.returnState) {
const parent = merge(a.parent, b.parent, rootIsWildcard, mergeCache);
if (parent === a.parent) {
return a;
}
if (parent === b.parent) {
return b;
}
const spc = createSingletonPredictionContext(parent, a.returnState);
if (mergeCache !== null) {
mergeCache.set(a, b, spc);
}
return spc;
} else {
let singleParent = null;
if (a === b || a.parent !== null && a.parent.equals(b.parent)) {
singleParent = a.parent;
}
if (singleParent !== null) {
const payloads2 = [a.returnState, b.returnState];
if (a.returnState > b.returnState) {
payloads2[0] = b.returnState;
payloads2[1] = a.returnState;
}
const parents2 = [singleParent, singleParent];
const apc = new ArrayPredictionContext(parents2, payloads2);
if (mergeCache !== null) {
mergeCache.set(a, b, apc);
}
return apc;
}
const payloads = [a.returnState, b.returnState];
let parents = [a.parent, b.parent];
if (a.returnState > b.returnState) {
payloads[0] = b.returnState;
payloads[1] = a.returnState;
parents = [b.parent, a.parent];
}
const aNew = new ArrayPredictionContext(parents, payloads);
if (mergeCache !== null) {
mergeCache.set(a, b, aNew);
}
return aNew;
}
}, "mergeSingletons");
var mergeRoot = /* @__PURE__ */ __name((a, b, rootIsWildcard) => {
if (rootIsWildcard) {
if (a === EmptyPredictionContext.instance || b === EmptyPredictionContext.instance) {
return EmptyPredictionContext.instance;
}
} else {
if (a === EmptyPredictionContext.instance && b === EmptyPredictionContext.instance) {
return EmptyPredictionContext.instance;
}
if (a === EmptyPredictionContext.instance) {
const payloads = [
b.returnState,
PredictionContext.EMPTY_RETURN_STATE
];
const parents = [b.parent, null];
return new ArrayPredictionContext(parents, payloads);
}
if (b === EmptyPredictionContext.instance) {
const payloads = [a.returnState, PredictionContext.EMPTY_RETURN_STATE];
const parents = [a.parent, null];
return new ArrayPredictionContext(parents, payloads);
}
}
return null;
}, "mergeRoot");
// src/atn/LL1Analyzer.ts
var LL1Analyzer = class _LL1Analyzer {
constructor(atn) {
this.atn = atn;
}
static {
__name(this, "LL1Analyzer");
}
/**
* Special value added to the lookahead sets to indicate that we hit
* a predicate during analysis if `seeThruPreds==false`.
*/
static hitPredicate = Token.INVALID_TYPE;
/**
* Calculates the SLL(1) expected lookahead set for each outgoing transition
* of an {@link ATNState}. The returned array has one element for each
* outgoing transition in `s`. If the closure from transition
* _i_ leads to a semantic predicate before matching a symbol, the
* element at index *i* of the result will be `undefined`.
*
* @param s the ATN state
* @returns the expected symbols for each outgoing transition of `s`.
*/
getDecisionLookahead(s) {
const count = s.transitions.length;
const look = new Array(count);
for (let alt = 0; alt < count; alt++) {
const set = new IntervalSet();
const lookBusy = new HashSet();
this.doLook(
s.transitions[alt].target,
void 0,
EmptyPredictionContext.instance,
set,
lookBusy,
new BitSet(),
false,
false
);
if (set.length > 0 && !set.contains(_LL1Analyzer.hitPredicate)) {
look[alt] = set;
}
}
return look;
}
/**
* Compute set of tokens that can follow `s` in the ATN in the
* specified `ctx`.
*
* If `ctx` is `null` and the end of the rule containing
* `s` is reached, {@link Token//EPSILON} is added to the result set.
* If `ctx` is not `null` and the end of the outermost rule is
* reached, {@link Token//EOF} is added to the result set.
*
* @param s the ATN state
* @param stopState the ATN state to stop at. This can be a
* {@link BlockEndState} to detect epsilon paths through a closure.
* @param ctx the complete parser context, or `null` if the context
* should be ignored
*
* @returns The set of tokens that can follow `s` in the ATN in the
* specified `ctx`.
*/
look(s, stopState, ctx) {
const r = new IntervalSet();
const lookContext = ctx ? predictionContextFromRuleContext(this.atn, ctx) : null;
this.doLook(s, stopState, lookContext, r, new HashSet(), new BitSet(), true, true);
return r;
}
/**
* Compute set of tokens that can follow `s` in the ATN in the
* specified `ctx`.
*
* If `ctx` is `null` and `stopState` or the end of the
* rule containing `s` is reached, {@link Token//EPSILON} is added to
* the result set. If `ctx` is not `null` and `addEOF` is
* `true` and `stopState` or the end of the outermost rule is
* reached, {@link Token//EOF} is added to the result set.
*
* @param s the ATN state.
* @param stopState the ATN state to stop at. This can be a
* {@link BlockEndState} to detect epsilon paths through a closure.
* @param ctx The outer context, or `null` if the outer context should
* not be used.
* @param look The result lookahead set.
* @param lookBusy A set used for preventing epsilon closures in the ATN
* from causing a stack overflow. Outside code should pass
* `new CustomizedSet<ATNConfig>` for this argument.
* @param calledRuleStack A set used for preventing left recursion in the
* ATN from causing a stack overflow. Outside code should pass
* `new BitSet()` for this argument.
* @param seeThruPreds `true` to true semantic predicates as
* implicitly `true` and "see through them", otherwise `false`
* to treat semantic predicates as opaque and add {@link hitPredicate} to the
* result if one is encountered.
* @param addEOF Add {@link Token//EOF} to the result if the end of the
* outermost context is reached. This parameter has no effect if `ctx`
* is `null`.
*/
doLook(s, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF) {
const c = ATNConfig.createWithContext(s, 0, ctx);
if (lookBusy.get(c)) {
return;
}
lookBusy.add(c);
if (s === stopState) {
if (!ctx) {
look.addOne(Token.EPSILON);
return;
} else if (ctx.isEmpty() && addEOF) {
look.addOne(Token.EOF);
return;
}
}
if (s.constructor.stateType === ATNState.RULE_STOP) {
if (!ctx) {
look.addOne(Token.EPSILON);
return;
} else if (ctx.isEmpty() && addEOF) {
look.addOne(Token.EOF);
return;
}
if (ctx !== EmptyPredictionContext.instance) {
const removed = calledRuleStack.get(s.ruleIndex);
try {
calledRuleStack.clear(s.ruleIndex);
for (let i = 0; i < ctx.length; i++) {
const returnState = this.atn.states[ctx.getReturnState(i)];
this.doLook(
returnState,
stopState,
ctx.getParent(i),
look,
lookBusy,
calledRuleStack,
seeThruPreds,
addEOF
);
}
} finally {
if (removed) {
calledRuleStack.set(s.ruleIndex);
}
}
return;
}
}
for (const t of s.transitions) {
switch (t.transitionType) {
case Transition.RULE: {
if (calledRuleStack.get(t.target.ruleIndex)) {
continue;
}
const newContext = createSingletonPredictionContext(
ctx ?? void 0,
t.followState.stateNumber
);
try {
calledRuleStack.set(t.target.ruleIndex);
this.doLook(
t.target,
stopState,
newContext,
look,
lookBusy,
calledRuleStack,
seeThruPreds,
addEOF
);
} finally {
calledRuleStack.clear(t.target.ruleIndex);
}
break;
}
case Transition.PREDICATE:
case Transition.PRECEDENCE: {
if (seeThruPreds) {
this.doLook(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
} else {
look.addOne(_LL1Analyzer.hitPredicate);
}
break;
}
case Transition.WILDCARD: {
look.addRange(Token.MIN_USER_TOKEN_TYPE, this.atn.maxTokenType);
break;
}
default: {
if (t.isEpsilon) {
this.doLook(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
} else {
let set = t.label;
if (set) {
if (t instanceof NotSetTransition) {
set = set.complement(Token.MIN_USER_TOKEN_TYPE, this.atn.maxTokenType);
}
look.addSet(set);
}
}
break;
}
}
}
}
};
// src/atn/ATN.ts
var ATN = class {
static {
__name(this, "ATN");
}
static INVALID_ALT_NUMBER = 0;
/** Represents the type of recognizer an ATN applies to */
static LEXER = 0;
static PARSER = 1;
/**
* Used for runtime deserialization of ATNs from strings
* The type of the ATN.
*/
grammarType;
/** The maximum value for any symbol recognized by a transition in the ATN. */
maxTokenType;
states = [];
/**
* Each subrule/rule is a decision point and we must track them so we
* can go back later and build DFA predictors for them. This includes
* all the rules, subrules, optional blocks, ()+, ()* etc...
*/
decisionToState = [];
/** Maps from rule index to starting state number. */
ruleToStartState = [];
// Initialized by the ATN deserializer.
/** Maps from rule index to stop state number. */
ruleToStopState = [];
// Initialized by the ATN deserializer.
modeNameToStartState = /* @__PURE__ */ new Map();
/**
* For lexer ATNs, this maps the rule index to the resulting token type.
* For parser ATNs, this maps the rule index to the generated bypass token
* type if the {@link ATNDeserializationOptions//isGenerateRuleBypassTransitions}
* deserialization option was specified; otherwise, this is `null`
*/
ruleToTokenType = [];
// Initialized by the ATN deserializer.
/**
* For lexer ATNs, this is an array of {@link LexerAction} objects which may
* be referenced by action transitions in the ATN
*/
lexerActions = [];
modeToStartState = [];
analyzer;
constructor(grammarType, maxTokenType) {
this.grammarType = grammarType;
this.maxTokenType = maxTokenType;
this.analyzer = new LL1Analyzer(this);
}
/**
* Compute the set of valid tokens that can occur starting in state `s`.
* If `ctx` is null, the set of tokens will not include what can follow
* the rule surrounding `s`. In other words, the set will be
* restricted to tokens reachable staying within `s`'s rule.
*/
nextTokens(atnState, ctx) {
if (!ctx && atnState.nextTokenWithinRule) {
return atnState.nextTokenWithinRule;
}
const next = this.analyzer.look(atnState, void 0, ctx);
if (!ctx) {
atnState.nextTokenWithinRule = next;
}
return next;
}
addState(state) {
if (state) {
state.stateNumber = this.states.length;
}
this.states.push(state);
}
removeState(state) {
this.states[state.stateNumber] = null;
}
defineDecisionState(s) {
this.decisionToState.push(s);
s.decision = this.decisionToState.length - 1;
return s.decision;
}
getDecisionState(decision) {
if (this.decisionToState.length === 0) {
return null;
} else {
return this.decisionToState[decision];
}
}
getNumberOfDecisions() {
return this.decisionToState.length;
}
/**
* Computes the set of input symbols which could follow ATN state number
* `stateNumber` in the specified full `context`. This method
* considers the complete parser context, but does not evaluate semantic
* predicates (i.e. all predicates encountered during the calculation are
* assumed true). If a path in the ATN exists from the starting state to the
* {@link RuleStopState} of the outermost context without matching any
* symbols, {@link Token//EOF} is added to the returned set.
*
* If `context` is `null`, it is treated as
* {@link ParserRuleContext//EMPTY}.
*
* @param stateNumber the ATN state number
* @param context the full parse context
*
* @returns {IntervalSet} The set of potentially valid input symbols which could follow the
* specified state in the specified context.
*
* @throws IllegalArgumentException if the ATN does not contain a state with
* number `stateNumber`
*/
getExpectedTokens(stateNumber, context) {
if (stateNumber < 0 || stateNumber >= this.states.length) {
throw new Error("Invalid state number.");
}
const s = this.states[stateNumber];
let following = this.nextTokens(s);
if (!following.contains(Token.EPSILON)) {
return following;
}
let ctx = context;
const expected = new IntervalSet();
expected.addSet(following);
expected.removeOne(Token.EPSILON);
while (ctx !== null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) {
const invokingState = this.states[ctx.invokingState];
const rt = invokingState.transitions[0];
following = this.nextTokens(rt.followState);
expected.addSet(following);
expected.removeOne(Token.EPSILON);
ctx = ctx.parent;
}
if (following.contains(Token.EPSILON)) {
expected.addOne(Token.EOF);
}
return expected;
}
};
// src/atn/ATNSimulator.ts
var ATNSimulator = class {
static {
__name(this, "ATNSimulator");
}
/** Must distinguish between missing edge and edge we know leads nowhere */
static ERROR = DFAState.fromState(2147483647);
atn;
/**
* The context cache maps all PredictionContext objects that are ==
* to a single cached copy. This cache is shared across all contexts
* in all ATNConfigs in all DFA states. We rebuild each ATNConfigSet
* to use only cached nodes/graphs in addDFAState(). We don't want to
* fill this during closure() since there are lots of contexts that
* pop up but are not used ever again. It also greatly slows down closure().
*
* This cache makes a huge difference in memory and a little bit in speed.
* For the Java grammar on java.*, it dropped the memory requirements
* at the end from 25M to 16M. We don't store any of the full context
* graphs in the DFA because they are limited to local context only,
* but apparently there's a lot of repetition there as well. We optimize
* the config contexts before storing the config set in the DFA states
* by literally rebuilding them with cached subgraphs only.
*
* I tried a cache for use during closure operations, that was
* whacked after each adaptivePredict(). It cost a little bit
* more time I think and doesn't save on the overall footprint
* so it's not worth the complexity.
*/
sharedContextCache;
constructor(atn, sharedContextCache) {
this.atn = atn;
this.sharedContextCache = sharedContextCache;
return this;
}
getCachedContext(context) {
if (!this.sharedContextCache) {
return context;
}
const visited = new HashMap(ObjectEqualityComparator.instance);
return getCachedPredictionContext(context, this.sharedContextCache, visited);
}
};
// src/atn/ATNConfigSet.ts
var KeyTypeEqualityComparer = class _KeyTypeEqualityComparer {
static {
__name(this, "KeyTypeEqualityComparer");
}
static instance = new _KeyTypeEqualityComparer();
hashCode(config) {
let hashCode = 7;
hashCode = 31 * hashCode + config.state.stateNumber;
hashCode = 31 * hashCode + config.alt;
hashCode = 31 * hashCode + config.semanticContext.hashCode();
return hashCode;
}
equals(a, b) {
if (a === b) {
return true;
}
return a.state.stateNumber === b.state.stateNumber && a.alt === b.alt && a.semanticContext.equals(b.semanticContext);
}
};
var ATNConfigSet = class {
static {
__name(this, "ATNConfigSet");
}
/**
* The reason that we need this is because we don't want the hash map to use
* the standard hash code and equals. We need all configurations with the
* same
* `(s,i,_,semctx)` to be equal. Unfortunately, this key effectively
* doubles
* the number of objects associated with ATNConfigs. The other solution is
* to
* use a hash table that lets us specify the equals/hashCode operation.
* All configs but hashed by (s, i, _, pi) not including context. Wiped out
* when we go readonly as this set becomes a DFA state
*/
configLookup = new HashSet(KeyTypeEqualityComparer.instance);
// Track the elements as they are added to the set; supports get(i).
configs = [];
uniqueAlt = 0;
/**
* Used in parser and lexer. In lexer, it indicates we hit a pred
* while computing a closure operation. Don't make a DFA state from this
*/
hasSemanticContext = false;
dipsIntoOuterContext = false;
/**
* Indicates that this configuration set is part of a full context
* LL prediction. It will be used to determine how to merge $. With SLL
* it's a wildcard whereas it is not for LL context merge
*/
fullCtx = false;
/**
* Indicates that the set of configurations is read-only. Do not
* allow any code to manipulate the set; DFA states will point at
* the sets and they must not change. This does not protect the other
* fields; in particular, conflictingAlts is set after
* we've made this readonly
*/
readOnly = false;
conflictingAlts = null;
/**
* Tracks the first config that has a rule stop state. Avoids frequent linear search for that, when adding
* a DFA state in the lexer ATN simulator.
*/
firstStopState;
#cachedHashCode = -1;
constructor(fullCtxOrOldSet) {
if (fullCtxOrOldSet !== void 0) {
if (typeof fullCtxOrOldSet === "boolean") {
this.fullCtx = fullCtxOrOldSet ?? true;
} else {
const old = fullCtxOrOldSet;
this.addAll(old.configs);
this.uniqueAlt = old.uniqueAlt;
this.conflictingAlts = old.conflictingAlts;
this.hasSemanticContext = old.hasSemanticContext;
this.dipsIntoOuterContext = old.dipsIntoOuterContext;
}
}
}
[Symbol.iterator]() {
return this.configs[Symbol.iterator]();
}
/**
* Adding a new config means merging contexts with existing configs for
* `(s, i, pi, _)`, where `s` is the {@link ATNConfig.state}, `i` is the {@link ATNConfig.alt}, and
* `pi` is the {@link ATNConfig.semanticContext}. We use `(s,i,pi)` as key.
*
* This method updates {@link dipsIntoOuterContext} and
* {@link hasSemanticContext} when necessary.
*/
add(config, mergeCache = null) {
if (this.readOnly) {
throw new Error("This set is readonly");
}
if (!this.firstStopState && config.state.constructor.stateType === ATNState.RULE_STOP) {
this.firstStopState = config;
}
this.hasSemanticContext ||= config.semanticContext !== SemanticContext.NONE;
this.dipsIntoOuterContext ||= config.reachesIntoOuterContext;
const existing = this.configLookup.getOrAdd(config);
if (existing === config) {
this.#cachedHashCode = -1;
this.configs.push(config);
return;
}
const rootIsWildcard = !this.fullCtx;
const merged = merge(existing.context, config.context, rootIsWildcard, mergeCache);
existing.reachesIntoOuterContext ||= config.reachesIntoOuterContext;
existing.precedenceFilterSuppressed ||= config.precedenceFilterSuppressed;
existing.context = merged;
}
/** Return a List holding list of configs */
get elements() {
return this.configs;
}
/**
* Gets the complete set of represented alternatives for the configuration set.
*
* @returns the set of represented alternatives in this configuration set
*/
getAlts() {
const alts = new BitSet();
for (const config of this.configs) {
alts.set(config.alt);
}
return alts;
}
getPredicates() {
const preds = [];
for (const config of this.configs) {
if (config.semanticContext !== SemanticContext.NONE) {
preds.push(config.semanticContext);
}
}
return preds;
}
getStates() {
const states = new HashSet();
for (const config of this.configs) {
states.add(config.state);
}
return states;
}
optimizeConfigs(interpreter) {
if (this.readOnly) {
throw new Error("This set is readonly");
}
if (this.configLookup.size === 0) {
return;
}
for (const config of this.configs) {
config.context = interpreter.getCachedContext(config.context);
}
}
addAll(coll) {
for (const config of coll) {
this.add(config);
}
return false;
}
equals(other) {
if (this === other) {
return true;
}
if (this.fullCtx === other.fullCtx && this.uniqueAlt === other.uniqueAlt && this.conflictingAlts === other.conflictingAlts && this.hasSemanticContext === other.hasSemanticContext && this.dipsIntoOuterContext === other.dipsIntoOuterContext && equalArrays(this.configs, other.configs)) {
return true;
}
return false;
}
hashCode() {
if (this.#cachedHashCode === -1) {
this.#cachedHashCode = this.computeHashCode();
}
return this.#cachedHashCode;
}
get length() {
return this.configs.length;
}
isEmpty() {
return this.configs.length === 0;
}
contains(item) {
if (this.configLookup === null) {
throw new Error("This method is not implemented for readonly sets.");
}
return this.configLookup.contains(item);
}
containsFast(item) {
if (this.configLookup === null) {
throw new Error("This method is not implemented for readonly sets.");
}
return this.configLookup.contains(item);
}
clear() {
if (this.readOnly) {
throw new Error("This set is readonly");
}
this.configs = [];
this.#cachedHashCode = -1;
this.configLookup = new HashSet(KeyTypeEqualityComparer.instance);
}
setReadonly(readOnly) {
this.readOnly = readOnly;
if (readOnly) {
this.configLookup = null;
}
}
toString() {
return arrayToString(this.configs) + (this.hasSemanticContext ? ",hasSemanticContext=" + this.hasSemanticContext : "") + (this.uniqueAlt !== ATN.INVALID_ALT_NUMBER ? ",uniqueAlt=" + this.uniqueAlt : "") + (this.conflictingAlts !== null ? ",conflictingAlts=" + this.conflictingAlts : "") + (this.dipsIntoOuterContext ? ",dipsIntoOuterContext" : "");
}
computeHashCode() {
let hash = MurmurHash.initialize();
this.configs.forEach((config) => {
hash = MurmurHash.update(hash, config.hashCode());
});
hash = MurmurHash.finish(hash, this.configs.length);
return hash;
}
};
// src/atn/LexerIndexedCustomAction.ts
var LexerIndexedCustomAction = class _LexerIndexedCustomAction {
static {
__name(this, "LexerIndexedCustomAction");
}
offset;
action;
actionType;
isPositionDependent = true;
cachedHashCode;
constructor(offset, action) {
this.actionType = action.actionType;
this.offset = offset;
this.action = action;
}
/**
* This method calls {@link execute} on the result of {@link getAction}
* using the provided `lexer`.
*/
execute(lexer) {
this.action.execute(lexer);
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hash = MurmurHash.initialize();
hash = MurmurHash.update(hash, this.offset);
hash = MurmurHash.updateFromComparable(hash, this.action);
this.cachedHashCode = MurmurHash.finish(hash, 2);
}
return this.cachedHashCode;
}
equals(other) {
if (this === other) {
return true;
}
if (!(other instanceof _LexerIndexedCustomAction)) {
return false;
}
return this.offset === other.offset && this.action === other.action;
}
};
// src/atn/LexerActionExecutor.ts
var LexerActionExecutor = class _LexerActionExecutor {
static {
__name(this, "LexerActionExecutor");
}
lexerActions;
actionType;
isPositionDependent = false;
cachedHashCode;
/**
* Represents an executor for a sequence of lexer actions which traversed during
* the matching operation of a lexer rule (token).
*
* The executor tracks position information for position-dependent lexer actions
* efficiently, ensuring that actions appearing only at the end of the rule do
* not cause bloating of the {@link DFA} created for the lexer.
*/
constructor(lexerActions) {
this.actionType = -1;
this.lexerActions = lexerActions ?? [];
return this;
}
/**
* Creates a {@link LexerActionExecutor} which executes the actions for
* the input `lexerActionExecutor` followed by a specified
* `lexerAction`.
*
* @param lexerActionExecutor The executor for actions already traversed by
* the lexer while matching a token within a particular
* {@link LexerATNConfig}. If this is `null`, the method behaves as
* though it were an empty executor.
* @param lexerAction The lexer action to execute after the actions
* specified in `lexerActionExecutor`.
*
* @returns {LexerActionExecutor} A {@link LexerActionExecutor} for executing the combine actions
* of `lexerActionExecutor` and `lexerAction`.
*/
static append(lexerActionExecutor, lexerAction) {
if (lexerActionExecutor === null) {
return new _LexerActionExecutor([lexerAction]);
}
const lexerActions = lexerActionExecutor.lexerActions.concat([lexerAction]);
return new _LexerActionExecutor(lexerActions);
}
/**
* Creates a {@link LexerActionExecutor} which encodes the current offset
* for position-dependent lexer actions.
*
* Normally, when the executor encounters lexer actions where
* {@link LexerAction//isPositionDependent} returns `true`, it calls
* {@link IntStream.seek} on the input {@link CharStream} to set the input
* position to the *end* of the current token. This behavior provides
* for efficient DFA representation of lexer actions which appear at the end
* of a lexer rule, even when the lexer rule matches a variable number of
* characters.
*
* Prior to traversing a match transition in the ATN, the current offset
* from the token start index is assigned to all position-dependent lexer
* actions which have not already been assigned a fixed offset. By storing
* the offsets relative to the token start index, the DFA representation of
* lexer actions which appear in the middle of tokens remains efficient due
* to sharing among tokens of the same length, regardless of their absolute
* position in the input stream.
*
* If the current executor already has offsets assigned to all
* position-dependent lexer actions, the method returns `this`.
*
* @param offset The current offset to assign to all position-dependent
* lexer actions which do not already have offsets assigned.
*
* @returns {LexerActionExecutor} A {@link LexerActionExecutor} which stores input stream offsets
* for all position-dependent lexer actions.
*/
fixOffsetBeforeMatch(offset) {
let updatedLexerActions = null;
for (let i = 0; i < this.lexerActions.length; i++) {
if (this.lexerActions[i].isPositionDependent && !(this.lexerActions[i] instanceof LexerIndexedCustomAction)) {
if (updatedLexerActions === null) {
updatedLexerActions = this.lexerActions.concat([]);
}
updatedLexerActions[i] = new LexerIndexedCustomAction(
offset,
this.lexerActions[i]
);
}
}
if (updatedLexerActions === null) {
return this;
} else {
return new _LexerActionExecutor(updatedLexerActions);
}
}
/**
* Execute the actions encapsulated by this executor within the context of a
* particular {@link Lexer}.
*
* This method calls {@link IntStream.seek} to set the position of the
* `input` {@link CharStream} prior to calling
* {@link LexerAction.execute} on a position-dependent action. Before the
* method returns, the input position will be restored to the same position
* it was in when the method was invoked.
*
* @param lexer The lexer instance.
* @param input The input stream which is the source for the current token.
* When this method is called, the current {@link IntStream.index} for
* `input` should be the start of the following token, i.e. 1
* character past the end of the current token.
* @param startIndex The token start index. This value may be passed to
* {@link IntStream.seek} to set the `input` position to the beginning
* of the token.
*/
execute(lexer, input, startIndex) {
if (input === void 0 || startIndex === void 0) {
return;
}
let requiresSeek = false;
const stopIndex = input.index;
try {
for (const lexerAction of this.lexerActions) {
let action = lexerAction;
if (lexerAction instanceof LexerIndexedCustomAction) {
const offset = lexerAction.offset;
input.seek(startIndex + offset);
action = lexerAction.action;
requiresSeek = startIndex + offset !== stopIndex;
} else if (lexerAction.isPositionDependent) {
input.seek(stopIndex);
requiresSeek = false;
}
action.execute(lexer);
}
} finally {
if (requiresSeek) {
input.seek(stopIndex);
}
}
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hashCode = MurmurHash.initialize(7);
for (const lexerAction of this.lexerActions) {
hashCode = MurmurHash.update(hashCode, lexerAction.hashCode());
}
this.cachedHashCode = MurmurHash.finish(hashCode, this.lexerActions.length);
}
return this.cachedHashCode;
}
equals(other) {
if (this === other) {
return true;
}
if (this.cachedHashCode !== other.cachedHashCode) {
return false;
}
if (this.lexerActions.length !== other.lexerActions.length) {
return false;
}
return this.lexerActions.every((action, index) => {
return action.equals(other.lexerActions[index]);
});
}
};
// src/misc/OrderedHashSet.ts
var OrderedHashSet = class _OrderedHashSet extends HashSet {
static {
__name(this, "OrderedHashSet");
}
elements = [];
getOrAdd(o) {
const oldSize = this.size;
const result = super.getOrAdd(o);
if (this.size > oldSize) {
this.elements.push(o);
}
return result;
}
equals(o) {
if (!(o instanceof _OrderedHashSet)) {
return false;
}
return super.equals(o);
}
clear() {
super.clear();
this.elements = [];
}
*[Symbol.iterator]() {
yield* this.elements;
}
toArray() {
return this.elements.slice(0);
}
};
// src/atn/OrderedATNConfigSet.ts
var OrderedATNConfigSet = class extends ATNConfigSet {
static {
__name(this, "OrderedATNConfigSet");
}
constructor() {
super();
this.configLookup = new OrderedHashSet();
}
};
// src/atn/LexerATNConfig.ts
var LexerATNConfig = class _LexerATNConfig extends ATNConfig {
static {
__name(this, "LexerATNConfig");
}
/**
* This is the backing field for {@link #getLexerActionExecutor}.
*/
lexerActionExecutor;
passedThroughNonGreedyDecision;
constructor(config, state, context, lexerActionExecutor) {
super(config, state, context ?? config.context, context ? SemanticContext.NONE : config.semanticContext);
this.lexerActionExecutor = context ? lexerActionExecutor : config.lexerActionExecutor ?? null;
this.passedThroughNonGreedyDecision = _LexerATNConfig.checkNonGreedyDecision(config, this.state);
return this;
}
static createWithExecutor(config, state, lexerActionExecutor) {
return new _LexerATNConfig(config, state, config.context, lexerActionExecutor);
}
static createWithConfig(state, config, context) {
return new _LexerATNConfig(config, state, context ?? null, config.lexerActionExecutor);
}
static createWithContext(state, alt, context) {
return new _LexerATNConfig({ alt }, state, context, null);
}
static checkNonGreedyDecision(source, target) {
return source.passedThroughNonGreedyDecision || "nonGreedy" in target && target.nonGreedy;
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hashCode = MurmurHash.initialize(7);
hashCode = MurmurHash.update(hashCode, this.state.stateNumber);
hashCode = MurmurHash.update(hashCode, this.alt);
hashCode = MurmurHash.updateFromComparable(hashCode, this.context);
hashCode = MurmurHash.updateFromComparable(hashCode, this.semanticContext);
hashCode = MurmurHash.update(hashCode, this.passedThroughNonGreedyDecision ? 1 : 0);
hashCode = MurmurHash.updateFromComparable(hashCode, this.lexerActionExecutor);
hashCode = MurmurHash.finish(hashCode, 6);
this.cachedHashCode = hashCode;
}
return this.cachedHashCode;
}
equals(other) {
if (this === other) {
return true;
}
return this.passedThroughNonGreedyDecision === other.passedThroughNonGreedyDecision && (this.lexerActionExecutor && other.lexerActionExecutor ? this.lexerActionExecutor.equals(other.lexerActionExecutor) : !other.lexerActionExecutor) && super.equals(other);
}
};
// src/atn/LexerATNSimulator.ts
var LexerATNSimulator = class _LexerATNSimulator extends ATNSimulator {
static {
__name(this, "LexerATNSimulator");
}
static debug = false;
decisionToDFA;
recognizer = null;
/**
* The current token's starting index into the character stream.
* Shared across DFA to ATN simulation in case the ATN fails and the
* DFA did not have a previous accept state. In this case, we use the
* ATN-generated exception object.
*/
startIndex = -1;
/** line number 1..n within the input */
line = 1;
/** The index of the character relative to the beginning of the line 0..n-1 */
column = 0;
mode = Lexer.DEFAULT_MODE;
/** Used during DFA/ATN exec to record the most recent accept configuration info */
prevAccept;
options;
/** Lookup table for lexer ATN config creation. */
lexerATNConfigFactory;
/**
* When we hit an accept state in either the DFA or the ATN, we
* have to notify the character stream to start buffering characters
* via {@link IntStream//mark} and record the current state. The current sim state
* includes the current index into the input, the current line,
* and current character position in that line. Note that the Lexer is
* tracking the starting line and characterization of the token. These
* variables track the "state" of the simulator when it hits an accept state.
*
* We track these variables separately for the DFA and ATN simulation
* because the DFA simulation often has to fail over to the ATN
* simulation. If the ATN simulation fails, we need the DFA to fall
* back to its previously accepted state, if any. If the ATN succeeds,
* then the ATN does the accept and the DFA simulator that invoked it
* can simply return the predicted token type.
*/
constructor(recog, atn, decisionToDFA, sharedContextCache) {
super(atn, sharedContextCache);
this.decisionToDFA = decisionToDFA;
this.recognizer = recog;
if (recog) {
this.options = recog.options;
} else {
this.options = {
minDFAEdge: 0,
maxDFAEdge: 256,
minCodePoint: 0,
maxCodePoint: 1114111
};
}
}
match(input, mode) {
this.mode = mode;
const mark = input.mark();
try {
this.startIndex = input.index;
this.prevAccept = void 0;
const dfa = this.decisionToDFA[mode];
if (!dfa.s0) {
return this.matchATN(input);
}
return this.execATN(input, dfa.s0);
} finally {
input.release(mark);
}
}
reset() {
this.prevAccept = void 0;
this.startIndex = -1;
this.line = 1;
this.column = 0;
this.mode = Lexer.DEFAULT_MODE;
}
clearDFA() {
for (let d = 0; d < this.decisionToDFA.length; d++) {
this.decisionToDFA[d] = new DFA(this.atn.getDecisionState(d), d);
}
}
getDFA(mode) {
return this.decisionToDFA[mode];
}
/** @returns the text matched so far for the current token. */
getText(input) {
return input.getTextFromRange(this.startIndex, input.index - 1);
}
consume(input) {
const curChar = input.LA(1);
if (curChar === "\n".charCodeAt(0)) {
this.line += 1;
this.column = 0;
} else {
this.column += 1;
}
input.consume();
}
getTokenName(tt) {
if (tt === Token.EOF) {
return "EOF";
} else {
return "'" + String.fromCharCode(tt) + "'";
}
}
matchATN(input) {
const startState = this.atn.modeToStartState[this.mode];
if (_LexerATNSimulator.debug) {
console.log("matchATN mode " + this.mode + " start: " + startState);
}
const oldMode = this.mode;
const s0Closure = this.computeStartState(input, startState);
const suppressEdge = s0Closure.hasSemanticContext;
s0Closure.hasSemanticContext = false;
const next = this.addDFAState(s0Closure);
if (!suppressEdge) {
this.decisionToDFA[this.mode].s0 = next;
}
const predict = this.execATN(input, next);
if (_LexerATNSimulator.debug) {
console.log("DFA after matchATN: " + this.decisionToDFA[oldMode].toLexerString());
}
return predict;
}
execATN(input, state) {
if (_LexerATNSimulator.debug) {
console.log("start state closure=" + state.configs);
}
if (state.isAcceptState) {
this.captureSimState(input, state);
}
let t = input.LA(1);
while (true) {
if (_LexerATNSimulator.debug) {
console.log("execATN loop starting closure: " + state.configs);
}
let target = this.getExistingTargetState(state, t);
if (!target) {
target = this.computeTargetState(input, state, t);
}
if (target === ATNSimulator.ERROR) {
break;
}
if (t !== Token.EOF) {
this.consume(input);
}
if (target.isAcceptState) {
this.captureSimState(input, target);
if (t === Token.EOF) {
break;
}
}
t = input.LA(1);
state = target;
}
return this.failOrAccept(input, state.configs, t);
}
/**
* Get an existing target state for an edge in the DFA. If the target state
* for the edge has not yet been computed or is otherwise not available,
* this method returns `null`.
*
* @param s The current DFA state.
* @param t The next input symbol.
*
* @returns The existing target DFA state for the given input symbol
* `t`, or `null` if the target state for this edge is not already cached
*/
getExistingTargetState(s, t) {
if (t >= this.options.minDFAEdge && t <= this.options.maxDFAEdge) {
const target = s.edges[t - this.options.minDFAEdge];
if (_LexerATNSimulator.debug && target) {
console.log("reuse state " + s.stateNumber + " edge to " + target.stateNumber);
}
return target;
}
return void 0;
}
/**
* Compute a target state for an edge in the DFA, and attempt to add the computed state and corresponding
* edge to the DFA.
*
* @param input The input stream
* @param s The current DFA state
* @param t The next input symbol
*
* @returns The computed target DFA state for the given input symbol `t`.
* If `t` does not lead to a valid DFA state, this method returns `ERROR`.
*/
computeTargetState(input, s, t) {
const reach = new OrderedATNConfigSet();
this.getReachableConfigSet(input, s.configs, reach, t);
if (reach.length === 0) {
if (!reach.hasSemanticContext) {
this.addDFAEdge(s, t, ATNSimulator.ERROR);
}
return ATNSimulator.ERROR;
}
return this.addDFAEdge(s, t, null, reach);
}
failOrAccept(input, reach, t) {
if (this.prevAccept?.dfaState) {
const { dfaState, index, line, column } = this.prevAccept;
this.accept(input, dfaState.lexerActionExecutor, this.startIndex, index, line, column);
return dfaState.prediction;
}
if (t === Token.EOF && input.index === this.startIndex) {
return Token.EOF;
}
throw new LexerNoViableAltException(this.recognizer, input, this.startIndex, reach);
}
/**
* Given a starting configuration set, figure out all ATN configurations we can reach upon input `t`.
* Parameter `reach` is a return parameter.
*/
getReachableConfigSet(input, closure, reach, t) {
let skipAlt = ATN.INVALID_ALT_NUMBER;
for (const cfg of closure) {
const currentAltReachedAcceptState = cfg.alt === skipAlt;
if (currentAltReachedAcceptState && cfg.passedThroughNonGreedyDecision) {
continue;
}
if (_LexerATNSimulator.debug) {
console.log("testing %s at %s\n", this.getTokenName(t), cfg.toString(this.recognizer, true));
}
for (const trans of cfg.state.transitions) {
const target = this.getReachableTarget(trans, t);
if (target) {
let lexerActionExecutor = cfg.lexerActionExecutor;
if (lexerActionExecutor) {
lexerActionExecutor = lexerActionExecutor.fixOffsetBeforeMatch(input.index - this.startIndex);
}
const treatEofAsEpsilon = t === Token.EOF;
const config = LexerATNConfig.createWithExecutor(
cfg,
target,
lexerActionExecutor
);
if (this.closure(input, config, reach, currentAltReachedAcceptState, true, treatEofAsEpsilon)) {
skipAlt = cfg.alt;
}
}
}
}
}
accept(input, lexerActionExecutor, startIndex, index, line, charPos) {
if (_LexerATNSimulator.debug) {
console.log("ACTION %s\n", lexerActionExecutor);
}
input.seek(index);
this.line = line;
this.column = charPos;
if (lexerActionExecutor && this.recognizer) {
lexerActionExecutor.execute(this.recognizer, input, startIndex);
}
}
getReachableTarget(trans, t) {
if (trans.matches(t, this.options.minCodePoint, this.options.maxCodePoint)) {
return trans.target;
} else {
return void 0;
}
}
computeStartState(input, p) {
const initialContext = EmptyPredictionContext.instance;
const configs = new OrderedATNConfigSet();
for (let i = 0; i < p.transitions.length; i++) {
const target = p.transitions[i].target;
const cfg = LexerATNConfig.createWithContext(target, i + 1, initialContext);
this.closure(input, cfg, configs, false, false, false);
}
return configs;
}
/**
* Since the alternatives within any lexer decision are ordered by
* preference, this method stops pursuing the closure as soon as an accept
* state is reached. After the first accept state is reached by depth-first
* search from `config`, all other (potentially reachable) states for
* this rule would have a lower priority.
*
* @returns {boolean} `true` if an accept state is reached, otherwise `false`.
*/
closure(input, config, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon) {
let cfg = null;
if (_LexerATNSimulator.debug) {
console.log("closure(" + config.toString(this.recognizer, true) + ")");
}
if (config.state.constructor.stateType === ATNState.RULE_STOP) {
if (_LexerATNSimulator.debug) {
if (this.recognizer !== null) {
console.log(
"closure at %s rule stop %s\n",
this.recognizer.ruleNames[config.state.ruleIndex],
config
);
} else {
console.log("closure at rule stop %s\n", config);
}
}
if (!config.context || config.context.hasEmptyPath()) {
if (!config.context || config.context.isEmpty()) {
configs.add(config);
return true;
} else {
configs.add(LexerATNConfig.createWithConfig(config.state, config, EmptyPredictionContext.instance));
currentAltReachedAcceptState = true;
}
}
if (config.context && !config.context.isEmpty()) {
for (let i = 0; i < config.context.length; i++) {
if (config.context.getReturnState(i) !== PredictionContext.EMPTY_RETURN_STATE) {
const newContext = config.context.getParent(i);
const returnState = this.atn.states[config.context.getReturnState(i)];
cfg = LexerATNConfig.createWithConfig(returnState, config, newContext);
currentAltReachedAcceptState = this.closure(
input,
cfg,
configs,
currentAltReachedAcceptState,
speculative,
treatEofAsEpsilon
);
}
}
}
return currentAltReachedAcceptState;
}
if (!config.state.epsilonOnlyTransitions) {
if (!currentAltReachedAcceptState || !config.passedThroughNonGreedyDecision) {
configs.add(config);
}
}
for (const trans of config.state.transitions) {
cfg = this.getEpsilonTarget(input, config, trans, configs, speculative, treatEofAsEpsilon);
if (cfg) {
currentAltReachedAcceptState = this.closure(
input,
cfg,
configs,
currentAltReachedAcceptState,
speculative,
treatEofAsEpsilon
);
}
}
return currentAltReachedAcceptState;
}
// side-effect: can alter configs.hasSemanticContext
getEpsilonTarget(input, config, trans, configs, speculative, treatEofAsEpsilon) {
if (!this.lexerATNConfigFactory) {
this.setupATNFactoryLookup();
}
const factory = this.lexerATNConfigFactory[trans.transitionType];
if (!factory) {
return null;
}
return factory(input, config, trans, configs, speculative, treatEofAsEpsilon);
}
/**
* Fills the lookup table for creating lexer ATN configs. This helps to avoid frequent checks of the transition
* type, which determines the configuration of the created config.
*/
setupATNFactoryLookup() {
this.lexerATNConfigFactory = [];
this.lexerATNConfigFactory[Transition.RULE] = (input, config, trans) => {
const newContext = createSingletonPredictionContext(
config.context ?? void 0,
trans.followState.stateNumber
);
return LexerATNConfig.createWithConfig(trans.target, config, newContext);
};
this.lexerATNConfigFactory[Transition.PRECEDENCE] = () => {
throw new Error("Precedence predicates are not supported in lexers.");
};
this.lexerATNConfigFactory[Transition.PREDICATE] = (input, config, trans, configs, speculative) => {
const pt = trans;
if (_LexerATNSimulator.debug) {
console.log("EVAL rule " + pt.ruleIndex + ":" + pt.predIndex);
}
configs.hasSemanticContext = true;
if (this.evaluatePredicate(input, pt.ruleIndex, pt.predIndex, speculative)) {
return LexerATNConfig.createWithConfig(trans.target, config);
}
return null;
};
this.lexerATNConfigFactory[Transition.ACTION] = (input, config, trans) => {
if (config.context === null || config.context.hasEmptyPath()) {
const lexerActionExecutor = LexerActionExecutor.append(
config.lexerActionExecutor,
this.atn.lexerActions[trans.actionIndex]
);
return LexerATNConfig.createWithExecutor(config, trans.target, lexerActionExecutor);
} else {
return LexerATNConfig.createWithConfig(trans.target, config);
}
};
this.lexerATNConfigFactory[Transition.EPSILON] = (input, config, trans) => {
return LexerATNConfig.createWithConfig(trans.target, config);
};
const simple = /* @__PURE__ */ __name((input, config, trans, configs, speculative, treatEofAsEpsilon) => {
if (treatEofAsEpsilon) {
if (trans.matches(Token.EOF, this.options.minCodePoint, this.options.maxCodePoint)) {
return LexerATNConfig.createWithConfig(trans.target, config);
}
}
return null;
}, "simple");
this.lexerATNConfigFactory[Transition.ATOM] = simple;
this.lexerATNConfigFactory[Transition.RANGE] = simple;
this.lexerATNConfigFactory[Transition.SET] = simple;
}
/**
* Evaluate a predicate specified in the lexer.
*
* If `speculative` is `true`, this method was called before
* {@link consume} for the matched character. This method should call
* {@link consume} before evaluating the predicate to ensure position
* sensitive values, including {@link Lexer//getText}, {@link Lexer//getLine},
* and {@link Lexer}, properly reflect the current
* lexer state. This method should restore `input` and the simulator
* to the original state before returning (i.e. undo the actions made by the
* call to {@link consume}.
*
* @param input The input stream.
* @param ruleIndex The rule containing the predicate.
* @param predIndex The index of the predicate within the rule.
* @param speculative `true` if the current index in `input` is
* one character before the predicate's location.
*
* @returns `true` if the specified predicate evaluates to
* `true`.
*/
evaluatePredicate(input, ruleIndex, predIndex, speculative) {
if (!this.recognizer) {
return true;
}
if (!speculative) {
return this.recognizer.sempred(null, ruleIndex, predIndex);
}
const savedColumn = this.column;
const savedLine = this.line;
const index = input.index;
const marker = input.mark();
try {
this.consume(input);
return this.recognizer.sempred(null, ruleIndex, predIndex);
} finally {
this.column = savedColumn;
this.line = savedLine;
input.seek(index);
input.release(marker);
}
}
captureSimState(input, dfaState) {
this.prevAccept = {
index: input.index,
line: this.line,
column: this.column,
dfaState
};
}
addDFAEdge(from, tk, to, configs) {
if (!to && configs) {
const suppressEdge = configs.hasSemanticContext;
configs.hasSemanticContext = false;
to = this.addDFAState(configs);
if (suppressEdge) {
return to;
}
}
if (tk < this.options.minDFAEdge || tk > this.options.maxDFAEdge) {
return to;
}
if (_LexerATNSimulator.debug) {
console.log("EDGE " + from + " -> " + to + " upon " + tk);
}
from.edges[tk - this.options.minDFAEdge] = to;
return to;
}
/**
* Add a new DFA state if there isn't one with this set of configurations already. This method also detects
* the first configuration containing an ATN rule stop state. Later, when traversing the DFA, we will know
* which rule to accept.
*/
addDFAState(configs) {
const dfa = this.decisionToDFA[this.mode];
const existing = dfa.getStateForConfigs(configs);
if (existing) {
return existing;
}
const proposed = DFAState.fromConfigs(configs);
const firstConfigWithRuleStopState = configs.firstStopState;
if (firstConfigWithRuleStopState) {
proposed.isAcceptState = true;
proposed.lexerActionExecutor = firstConfigWithRuleStopState.lexerActionExecutor;
proposed.prediction = this.atn.ruleToTokenType[firstConfigWithRuleStopState.state.ruleIndex];
}
configs.setReadonly(true);
dfa.addState(proposed);
return proposed;
}
};
export {
LexerATNSimulator
};