antlr4-runtime
Version:
JavaScript runtime for ANTLR4
160 lines (139 loc) • 5.06 kB
JavaScript
/* Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
import Token from './Token.js';
import ConsoleErrorListener from './error/ConsoleErrorListener.js';
import ProxyErrorListener from './error/ProxyErrorListener.js';
export default class Recognizer {
constructor() {
this._listeners = [ ConsoleErrorListener.INSTANCE ];
this._interp = null;
this._stateNumber = -1;
}
checkVersion(toolVersion) {
const runtimeVersion = "4.13.0";
if (runtimeVersion!==toolVersion) {
console.log("ANTLR runtime and generated code versions disagree: "+runtimeVersion+"!="+toolVersion);
}
}
addErrorListener(listener) {
this._listeners.push(listener);
}
removeErrorListeners() {
this._listeners = [];
}
getLiteralNames() {
return Object.getPrototypeOf(this).constructor.literalNames || [];
}
getSymbolicNames() {
return Object.getPrototypeOf(this).constructor.symbolicNames || [];
}
getTokenNames() {
if(!this.tokenNames) {
const literalNames = this.getLiteralNames();
const symbolicNames = this.getSymbolicNames();
const length = literalNames.length > symbolicNames.length ? literalNames.length : symbolicNames.length;
this.tokenNames = [];
for(let i=0; i<length; i++) {
this.tokenNames[i] = literalNames[i] || symbolicNames[i] || "<INVALID";
}
}
return this.tokenNames;
}
getTokenTypeMap() {
const tokenNames = this.getTokenNames();
if (tokenNames===null) {
throw("The current recognizer does not provide a list of token names.");
}
let result = this.tokenTypeMapCache[tokenNames];
if(result===undefined) {
result = tokenNames.reduce(function(o, k, i) { o[k] = i; });
result.EOF = Token.EOF;
this.tokenTypeMapCache[tokenNames] = result;
}
return result;
}
/**
* Get a map from rule names to rule indexes.
* <p>Used for XPath and tree pattern compilation.</p>
*/
getRuleIndexMap() {
const ruleNames = this.ruleNames;
if (ruleNames===null) {
throw("The current recognizer does not provide a list of rule names.");
}
let result = this.ruleIndexMapCache[ruleNames]; // todo: should it be Recognizer.ruleIndexMapCache ?
if(result===undefined) {
result = ruleNames.reduce(function(o, k, i) { o[k] = i; });
this.ruleIndexMapCache[ruleNames] = result;
}
return result;
}
getTokenType(tokenName) {
const ttype = this.getTokenTypeMap()[tokenName];
if (ttype !==undefined) {
return ttype;
} else {
return Token.INVALID_TYPE;
}
}
// What is the error header, normally line/character position information?
getErrorHeader(e) {
const line = e.getOffendingToken().line;
const column = e.getOffendingToken().column;
return "line " + line + ":" + column;
}
/**
* How should a token be displayed in an error message? The default
* is to display just the text, but during development you might
* want to have a lot of information spit out. Override in that case
* to use t.toString() (which, for CommonToken, dumps everything about
* the token). This is better than forcing you to override a method in
* your token objects because you don't have to go modify your lexer
* so that it creates a new Java type.
*
* @deprecated This method is not called by the ANTLR 4 Runtime. Specific
* implementations of {@link ANTLRErrorStrategy} may provide a similar
* feature when necessary. For example, see
* {@link DefaultErrorStrategy//getTokenErrorDisplay}.*/
getTokenErrorDisplay(t) {
if (t===null) {
return "<no token>";
}
let s = t.text;
if (s===null) {
if (t.type===Token.EOF) {
s = "<EOF>";
} else {
s = "<" + t.type + ">";
}
}
s = s.replace("\n","\\n").replace("\r","\\r").replace("\t","\\t");
return "'" + s + "'";
}
getErrorListenerDispatch() {
return new ProxyErrorListener(this._listeners);
}
/**
* subclass needs to override these if there are sempreds or actions
* that the ATN interp needs to execute
*/
sempred(localctx, ruleIndex, actionIndex) {
return true;
}
precpred(localctx , precedence) {
return true;
}
get atn() {
return this._interp.atn;
}
get state(){
return this._stateNumber;
}
set state(state) {
this._stateNumber = state;
}
}
Recognizer.tokenTypeMapCache = {};
Recognizer.ruleIndexMapCache = {};