Merge pull request #2771 from carocad/atn-es6

Javascript: migrate prototypical ATN objects to ES6
This commit is contained in:
Terence Parr 2020-03-09 09:17:49 -07:00 committed by GitHub
commit 1284814c21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 5181 additions and 5170 deletions

View File

@ -7,8 +7,8 @@ var Token = require('./Token').Token;
var ParseTreeListener = require('./tree/Tree').ParseTreeListener; var ParseTreeListener = require('./tree/Tree').ParseTreeListener;
var Recognizer = require('./Recognizer').Recognizer; var Recognizer = require('./Recognizer').Recognizer;
var DefaultErrorStrategy = require('./error/ErrorStrategy').DefaultErrorStrategy; var DefaultErrorStrategy = require('./error/ErrorStrategy').DefaultErrorStrategy;
var ATNDeserializer = require('./atn/ATNDeserializer').ATNDeserializer; var ATNDeserializer = require('./atn/ATNDeserializer');
var ATNDeserializationOptions = require('./atn/ATNDeserializationOptions').ATNDeserializationOptions; var ATNDeserializationOptions = require('./atn/ATNDeserializationOptions');
var TerminalNode = require('./tree/Tree').TerminalNode; var TerminalNode = require('./tree/Tree').TerminalNode;
var ErrorNode = require('./tree/Tree').ErrorNode; var ErrorNode = require('./tree/Tree').ErrorNode;
@ -671,4 +671,4 @@ Parser.prototype.setTrace = function(trace) {
} }
}; };
exports.Parser = Parser; exports.Parser = Parser;

View File

@ -3,139 +3,153 @@
* can be found in the LICENSE.txt file in the project root. * can be found in the LICENSE.txt file in the project root.
*/ */
var LL1Analyzer = require('./../LL1Analyzer').LL1Analyzer; const {LL1Analyzer} = require('./../LL1Analyzer');
var IntervalSet = require('./../IntervalSet').IntervalSet; const {IntervalSet} = require('./../IntervalSet');
const {Token} = require('./../Token');
function ATN(grammarType , maxTokenType) { class ATN {
constructor(grammarType , maxTokenType) {
// Used for runtime deserialization of ATNs from strings/// /**
// The type of the ATN. * Used for runtime deserialization of ATNs from strings
this.grammarType = grammarType; * The type of the ATN.
// The maximum value for any symbol recognized by a transition in the ATN. */
this.maxTokenType = maxTokenType; this.grammarType = grammarType;
this.states = []; // The maximum value for any symbol recognized by a transition in the ATN.
// Each subrule/rule is a decision point and we must track them so we this.maxTokenType = maxTokenType;
// can go back later and build DFA predictors for them. This includes this.states = [];
// all the rules, subrules, optional blocks, ()+, ()* etc... /**
this.decisionToState = []; * Each subrule/rule is a decision point and we must track them so we
// Maps from rule index to starting state number. * can go back later and build DFA predictors for them. This includes
this.ruleToStartState = []; * all the rules, subrules, optional blocks, ()+, ()* etc...
// Maps from rule index to stop state number. */
this.ruleToStopState = null; this.decisionToState = [];
this.modeNameToStartState = {}; // Maps from rule index to starting state number.
// For lexer ATNs, this maps the rule index to the resulting token type. this.ruleToStartState = [];
// For parser ATNs, this maps the rule index to the generated bypass token // Maps from rule index to stop state number.
// type if the this.ruleToStopState = null;
// {@link ATNDeserializationOptions//isGenerateRuleBypassTransitions} this.modeNameToStartState = {};
// deserialization option was specified; otherwise, this is {@code null}. /**
this.ruleToTokenType = null; * For lexer ATNs, this maps the rule index to the resulting token type.
// For lexer ATNs, this is an array of {@link LexerAction} objects which may * For parser ATNs, this maps the rule index to the generated bypass token
// be referenced by action transitions in the ATN. * type if the {@link ATNDeserializationOptions//isGenerateRuleBypassTransitions}
this.lexerActions = null; * deserialization option was specified; otherwise, this is {@code null}
this.modeToStartState = []; */
this.ruleToTokenType = null;
/**
* For lexer ATNs, this is an array of {@link LexerAction} objects which may
* be referenced by action transitions in the ATN
*/
this.lexerActions = null;
this.modeToStartState = [];
}
return this; /**
} * Compute the set of valid tokens that can occur starting in state {@code s}.
* If {@code ctx} is null, the set of tokens will not include what can follow
* the rule surrounding {@code s}. In other words, the set will be
* restricted to tokens reachable staying within {@code s}'s rule
*/
nextTokensInContext(s, ctx) {
const anal = new LL1Analyzer(this);
return anal.LOOK(s, null, ctx);
}
// Compute the set of valid tokens that can occur starting in state {@code s}. /**
// If {@code ctx} is null, the set of tokens will not include what can follow * Compute the set of valid tokens that can occur starting in {@code s} and
// the rule surrounding {@code s}. In other words, the set will be * staying in same rule. {@link Token//EPSILON} is in set if we reach end of
// restricted to tokens reachable staying within {@code s}'s rule. * rule
ATN.prototype.nextTokensInContext = function(s, ctx) { */
var anal = new LL1Analyzer(this); nextTokensNoContext(s) {
return anal.LOOK(s, null, ctx); if (s.nextTokenWithinRule !== null ) {
}; return s.nextTokenWithinRule;
}
// Compute the set of valid tokens that can occur starting in {@code s} and s.nextTokenWithinRule = this.nextTokensInContext(s, null);
// staying in same rule. {@link Token//EPSILON} is in set if we reach end of s.nextTokenWithinRule.readOnly = true;
// rule.
ATN.prototype.nextTokensNoContext = function(s) {
if (s.nextTokenWithinRule !== null ) {
return s.nextTokenWithinRule; return s.nextTokenWithinRule;
} }
s.nextTokenWithinRule = this.nextTokensInContext(s, null);
s.nextTokenWithinRule.readOnly = true;
return s.nextTokenWithinRule;
};
ATN.prototype.nextTokens = function(s, ctx) { nextTokens(s, ctx) {
if ( ctx===undefined ) { if ( ctx===undefined ) {
return this.nextTokensNoContext(s); return this.nextTokensNoContext(s);
} else { } else {
return this.nextTokensInContext(s, ctx); return this.nextTokensInContext(s, ctx);
}
} }
};
ATN.prototype.addState = function( state) { addState(state) {
if ( state !== null ) { if ( state !== null ) {
state.atn = this; state.atn = this;
state.stateNumber = this.states.length; state.stateNumber = this.states.length;
}
this.states.push(state);
} }
this.states.push(state);
};
ATN.prototype.removeState = function( state) { removeState(state) {
this.states[state.stateNumber] = null; // just free mem, don't shift states in list this.states[state.stateNumber] = null; // just free mem, don't shift states in list
};
ATN.prototype.defineDecisionState = function( s) {
this.decisionToState.push(s);
s.decision = this.decisionToState.length-1;
return s.decision;
};
ATN.prototype.getDecisionState = function( decision) {
if (this.decisionToState.length===0) {
return null;
} else {
return this.decisionToState[decision];
} }
};
// Computes the set of input symbols which could follow ATN state number defineDecisionState(s) {
// {@code stateNumber} in the specified full {@code context}. This method this.decisionToState.push(s);
// considers the complete parser context, but does not evaluate semantic s.decision = this.decisionToState.length-1;
// predicates (i.e. all predicates encountered during the calculation are return s.decision;
// 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.
//
// <p>If {@code context} is {@code null}, it is treated as
// {@link ParserRuleContext//EMPTY}.</p>
//
// @param stateNumber the ATN state number
// @param context the full parse context
// @return 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 {@code stateNumber}
var Token = require('./../Token').Token;
ATN.prototype.getExpectedTokens = function( stateNumber, ctx ) { getDecisionState(decision) {
if ( stateNumber < 0 || stateNumber >= this.states.length ) { if (this.decisionToState.length===0) {
throw("Invalid state number."); return null;
} else {
return this.decisionToState[decision];
}
} }
var s = this.states[stateNumber];
var following = this.nextTokens(s); /**
if (!following.contains(Token.EPSILON)) { * Computes the set of input symbols which could follow ATN state number
return following; * {@code stateNumber} in the specified full {@code context}. This method
} * considers the complete parser context, but does not evaluate semantic
var expected = new IntervalSet(); * predicates (i.e. all predicates encountered during the calculation are
expected.addSet(following); * assumed true). If a path in the ATN exists from the starting state to the
expected.removeOne(Token.EPSILON); * {@link RuleStopState} of the outermost context without matching any
while (ctx !== null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) { * symbols, {@link Token//EOF} is added to the returned set.
var invokingState = this.states[ctx.invokingState]; *
var rt = invokingState.transitions[0]; * <p>If {@code context} is {@code null}, it is treated as
following = this.nextTokens(rt.followState); * {@link ParserRuleContext//EMPTY}.</p>
*
* @param stateNumber the ATN state number
* @param ctx the full parse context
*
* @return {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 {@code stateNumber}
*/
getExpectedTokens(stateNumber, ctx ) {
if ( stateNumber < 0 || stateNumber >= this.states.length ) {
throw("Invalid state number.");
}
const s = this.states[stateNumber];
let following = this.nextTokens(s);
if (!following.contains(Token.EPSILON)) {
return following;
}
const expected = new IntervalSet();
expected.addSet(following); expected.addSet(following);
expected.removeOne(Token.EPSILON); expected.removeOne(Token.EPSILON);
ctx = ctx.parentCtx; 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.parentCtx;
}
if (following.contains(Token.EPSILON)) {
expected.addOne(Token.EOF);
}
return expected;
} }
if (following.contains(Token.EPSILON)) { }
expected.addOne(Token.EOF);
}
return expected;
};
ATN.INVALID_ALT_NUMBER = 0; ATN.INVALID_ALT_NUMBER = 0;

View File

@ -1,32 +1,22 @@
//
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
///
// A tuple: (ATN state, predicted alt, syntactic, semantic context). const {DecisionState} = require('./ATNState');
// The syntactic context is a graph-structured stack node whose const {SemanticContext} = require('./SemanticContext');
// path(s) to the root is the rule invocation(s) const {Hash} = require("../Utils");
// chain used to arrive at the state. The semantic context is
// the tree of semantic predicates encountered before reaching
// an ATN state.
///
var DecisionState = require('./ATNState').DecisionState;
var SemanticContext = require('./SemanticContext').SemanticContext;
var Hash = require("../Utils").Hash;
function checkParams(params, isCfg) { function checkParams(params, isCfg) {
if(params===null) { if(params===null) {
var result = { state:null, alt:null, context:null, semanticContext:null }; const result = { state:null, alt:null, context:null, semanticContext:null };
if(isCfg) { if(isCfg) {
result.reachesIntoOuterContext = 0; result.reachesIntoOuterContext = 0;
} }
return result; return result;
} else { } else {
var props = {}; const props = {};
props.state = params.state || null; props.state = params.state || null;
props.alt = (params.alt === undefined) ? null : params.alt; props.alt = (params.alt === undefined) ? null : params.alt;
props.context = params.context || null; props.context = params.context || null;
@ -39,138 +29,144 @@ function checkParams(params, isCfg) {
} }
} }
function ATNConfig(params, config) { class ATNConfig {
this.checkContext(params, config); /**
params = checkParams(params); * @param {Object} params A tuple: (ATN state, predicted alt, syntactic, semantic context).
config = checkParams(config, true); * The syntactic context is a graph-structured stack node whose
// The ATN state associated with this configuration/// * path(s) to the root is the rule invocation(s)
this.state = params.state!==null ? params.state : config.state; * chain used to arrive at the state. The semantic context is
// What alt (or lexer rule) is predicted by this configuration/// * the tree of semantic predicates encountered before reaching
this.alt = params.alt!==null ? params.alt : config.alt; * an ATN state
// The stack of invoking states leading to the rule/states associated */
// with this config. We track only those contexts pushed during constructor(params, config) {
// execution of the ATN simulator. this.checkContext(params, config);
this.context = params.context!==null ? params.context : config.context; params = checkParams(params);
this.semanticContext = params.semanticContext!==null ? params.semanticContext : config = checkParams(config, true);
(config.semanticContext!==null ? config.semanticContext : SemanticContext.NONE); // The ATN state associated with this configuration///
// We cannot execute predicates dependent upon local context unless this.state = params.state!==null ? params.state : config.state;
// we know for sure we are in the correct context. Because there is // What alt (or lexer rule) is predicted by this configuration///
// no way to do this efficiently, we simply cannot evaluate this.alt = params.alt!==null ? params.alt : config.alt;
// dependent predicates unless we are in the rule that initially /**
// invokes the ATN simulator. * The stack of invoking states leading to the rule/states associated
// * with this config. We track only those contexts pushed during
// closure() tracks the depth of how far we dip into the * execution of the ATN simulator
// outer context: depth &gt; 0. Note that it may not be totally */
// accurate depth since I don't ever decrement. TODO: make it a boolean then this.context = params.context!==null ? params.context : config.context;
this.reachesIntoOuterContext = config.reachesIntoOuterContext; this.semanticContext = params.semanticContext!==null ? params.semanticContext :
this.precedenceFilterSuppressed = config.precedenceFilterSuppressed; (config.semanticContext!==null ? config.semanticContext : SemanticContext.NONE);
return this; // TODO: make it a boolean then
/**
* 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 &gt; 0. Note that it may not be totally
* accurate depth since I don't ever decrement
*/
this.reachesIntoOuterContext = config.reachesIntoOuterContext;
this.precedenceFilterSuppressed = config.precedenceFilterSuppressed;
}
checkContext(params, config) {
if((params.context===null || params.context===undefined) &&
(config===null || config.context===null || config.context===undefined)) {
this.context = null;
}
}
hashCode() {
const hash = new Hash();
this.updateHashCode(hash);
return hash.finish();
}
updateHashCode(hash) {
hash.update(this.state.stateNumber, this.alt, this.context, this.semanticContext);
}
/**
* 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;
} else if (! (other instanceof ATNConfig)) {
return false;
} else {
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;
}
}
hashCodeForConfigSet() {
const hash = new Hash();
hash.update(this.state.stateNumber, this.alt, this.semanticContext);
return hash.finish();
}
equalsForConfigSet(other) {
if (this === other) {
return true;
} else if (! (other instanceof ATNConfig)) {
return false;
} else {
return this.state.stateNumber===other.state.stateNumber &&
this.alt===other.alt &&
this.semanticContext.equals(other.semanticContext);
}
}
toString() {
return "(" + this.state + "," + this.alt +
(this.context!==null ? ",[" + this.context.toString() + "]" : "") +
(this.semanticContext !== SemanticContext.NONE ?
("," + this.semanticContext.toString())
: "") +
(this.reachesIntoOuterContext>0 ?
(",up=" + this.reachesIntoOuterContext)
: "") + ")";
}
} }
ATNConfig.prototype.checkContext = function(params, config) {
if((params.context===null || params.context===undefined) &&
(config===null || config.context===null || config.context===undefined)) {
this.context = null;
}
};
class LexerATNConfig extends ATNConfig {
constructor(params, config) {
super(params, config);
ATNConfig.prototype.hashCode = function() { // This is the backing field for {@link //getLexerActionExecutor}.
var hash = new Hash(); const lexerActionExecutor = params.lexerActionExecutor || null;
this.updateHashCode(hash); this.lexerActionExecutor = lexerActionExecutor || (config!==null ? config.lexerActionExecutor : null);
return hash.finish(); this.passedThroughNonGreedyDecision = config!==null ? this.checkNonGreedyDecision(config, this.state) : false;
}; this.hashCodeForConfigSet = LexerATNConfig.prototype.hashCode;
this.equalsForConfigSet = LexerATNConfig.prototype.equals;
return this;
ATNConfig.prototype.updateHashCode = function(hash) {
hash.update(this.state.stateNumber, this.alt, this.context, this.semanticContext);
};
// 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.
ATNConfig.prototype.equals = function(other) {
if (this === other) {
return true;
} else if (! (other instanceof ATNConfig)) {
return false;
} else {
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;
} }
};
updateHashCode(hash) {
ATNConfig.prototype.hashCodeForConfigSet = function() { hash.update(this.state.stateNumber, this.alt, this.context, this.semanticContext, this.passedThroughNonGreedyDecision, this.lexerActionExecutor);
var hash = new Hash();
hash.update(this.state.stateNumber, this.alt, this.semanticContext);
return hash.finish();
};
ATNConfig.prototype.equalsForConfigSet = function(other) {
if (this === other) {
return true;
} else if (! (other instanceof ATNConfig)) {
return false;
} else {
return this.state.stateNumber===other.state.stateNumber &&
this.alt===other.alt &&
this.semanticContext.equals(other.semanticContext);
} }
};
equals(other) {
return this === other ||
(other instanceof LexerATNConfig &&
this.passedThroughNonGreedyDecision == other.passedThroughNonGreedyDecision &&
(this.lexerActionExecutor ? this.lexerActionExecutor.equals(other.lexerActionExecutor) : !other.lexerActionExecutor) &&
super.equals(other));
}
ATNConfig.prototype.toString = function() { checkNonGreedyDecision(source, target) {
return "(" + this.state + "," + this.alt + return source.passedThroughNonGreedyDecision ||
(this.context!==null ? ",[" + this.context.toString() + "]" : "") + (target instanceof DecisionState) && target.nonGreedy;
(this.semanticContext !== SemanticContext.NONE ? }
("," + this.semanticContext.toString())
: "") +
(this.reachesIntoOuterContext>0 ?
(",up=" + this.reachesIntoOuterContext)
: "") + ")";
};
function LexerATNConfig(params, config) {
ATNConfig.call(this, params, config);
// This is the backing field for {@link //getLexerActionExecutor}.
var lexerActionExecutor = params.lexerActionExecutor || null;
this.lexerActionExecutor = lexerActionExecutor || (config!==null ? config.lexerActionExecutor : null);
this.passedThroughNonGreedyDecision = config!==null ? this.checkNonGreedyDecision(config, this.state) : false;
return this;
} }
LexerATNConfig.prototype = Object.create(ATNConfig.prototype);
LexerATNConfig.prototype.constructor = LexerATNConfig;
LexerATNConfig.prototype.updateHashCode = function(hash) { module.exports.ATNConfig = ATNConfig;
hash.update(this.state.stateNumber, this.alt, this.context, this.semanticContext, this.passedThroughNonGreedyDecision, this.lexerActionExecutor); module.exports.LexerATNConfig = LexerATNConfig;
};
LexerATNConfig.prototype.equals = function(other) {
return this === other ||
(other instanceof LexerATNConfig &&
this.passedThroughNonGreedyDecision == other.passedThroughNonGreedyDecision &&
(this.lexerActionExecutor ? this.lexerActionExecutor.equals(other.lexerActionExecutor) : !other.lexerActionExecutor) &&
ATNConfig.prototype.equals.call(this, other));
};
LexerATNConfig.prototype.hashCodeForConfigSet = LexerATNConfig.prototype.hashCode;
LexerATNConfig.prototype.equalsForConfigSet = LexerATNConfig.prototype.equals;
LexerATNConfig.prototype.checkNonGreedyDecision = function(source, target) {
return source.passedThroughNonGreedyDecision ||
(target instanceof DecisionState) && target.nonGreedy;
};
exports.ATNConfig = ATNConfig;
exports.LexerATNConfig = LexerATNConfig;

View File

@ -1,21 +1,12 @@
//
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
// const ATN = require('./ATN');
// Specialized {@link Set}{@code <}{@link ATNConfig}{@code >} that can track const Utils = require('./../Utils');
// info about the set, with support for combining similar configurations using a const {SemanticContext} = require('./SemanticContext');
// graph-structured stack. const {merge} = require('./../PredictionContext');
///
var ATN = require('./ATN');
var Utils = require('./../Utils');
var Hash = Utils.Hash;
var Set = Utils.Set;
var SemanticContext = require('./SemanticContext').SemanticContext;
var merge = require('./../PredictionContext').merge;
function hashATNConfig(c) { function hashATNConfig(c) {
return c.hashCodeForConfigSet(); return c.hashCodeForConfigSet();
@ -30,224 +21,233 @@ function equalATNConfigs(a, b) {
return a.equalsForConfigSet(b); return a.equalsForConfigSet(b);
} }
/**
* Specialized {@link Set}{@code <}{@link ATNConfig}{@code >} that can track
* info about the set, with support for combining similar configurations using a
* graph-structured stack
*/
class ATNConfigSet {
constructor(fullCtx) {
/**
* 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
* {@code (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
*/
this.configLookup = new Utils.Set(hashATNConfig, equalATNConfigs);
/**
* 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
*/
this.fullCtx = fullCtx === undefined ? true : fullCtx;
/**
* 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
*/
this.readOnly = false;
// Track the elements as they are added to the set; supports get(i)///
this.configs = [];
function ATNConfigSet(fullCtx) { // TODO: these fields make me pretty uncomfortable but nice to pack up info
// // together, saves recomputation
// The reason that we need this is because we don't want the hash map to use // TODO: can we track conflicts as they are added to save scanning configs
// the standard hash code and equals. We need all configurations with the // later?
// same this.uniqueAlt = 0;
// {@code (s,i,_,semctx)} to be equal. Unfortunately, this key effectively this.conflictingAlts = null;
// 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.
this.configLookup = new Set(hashATNConfig, equalATNConfigs);
// 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.
this.fullCtx = fullCtx === undefined ? true : fullCtx;
// 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.
this.readOnly = false;
// Track the elements as they are added to the set; supports get(i)///
this.configs = [];
// TODO: these fields make me pretty uncomfortable but nice to pack up info /**
// together, saves recomputation * Used in parser and lexer. In lexer, it indicates we hit a pred
// TODO: can we track conflicts as they are added to save scanning configs * while computing a closure operation. Don't make a DFA state from this
// later? */
this.uniqueAlt = 0; this.hasSemanticContext = false;
this.conflictingAlts = null; this.dipsIntoOuterContext = false;
// 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.
this.hasSemanticContext = false;
this.dipsIntoOuterContext = false;
this.cachedHashCode = -1;
return this;
}
// Adding a new config means merging contexts with existing configs for
// {@code (s, i, pi, _)}, where {@code s} is the
// {@link ATNConfig//state}, {@code i} is the {@link ATNConfig//alt}, and
// {@code pi} is the {@link ATNConfig//semanticContext}. We use
// {@code (s,i,pi)} as key.
//
// <p>This method updates {@link //dipsIntoOuterContext} and
// {@link //hasSemanticContext} when necessary.</p>
// /
ATNConfigSet.prototype.add = function(config, mergeCache) {
if (mergeCache === undefined) {
mergeCache = null;
}
if (this.readOnly) {
throw "This set is readonly";
}
if (config.semanticContext !== SemanticContext.NONE) {
this.hasSemanticContext = true;
}
if (config.reachesIntoOuterContext > 0) {
this.dipsIntoOuterContext = true;
}
var existing = this.configLookup.add(config);
if (existing === config) {
this.cachedHashCode = -1; this.cachedHashCode = -1;
this.configs.push(config); // track order here }
/**
* Adding a new config means merging contexts with existing configs for
* {@code (s, i, pi, _)}, where {@code s} is the
* {@link ATNConfig//state}, {@code i} is the {@link ATNConfig//alt}, and
* {@code pi} is the {@link ATNConfig//semanticContext}. We use
* {@code (s,i,pi)} as key.
*
* <p>This method updates {@link //dipsIntoOuterContext} and
* {@link //hasSemanticContext} when necessary.</p>
*/
add(config, mergeCache) {
if (mergeCache === undefined) {
mergeCache = null;
}
if (this.readOnly) {
throw "This set is readonly";
}
if (config.semanticContext !== SemanticContext.NONE) {
this.hasSemanticContext = true;
}
if (config.reachesIntoOuterContext > 0) {
this.dipsIntoOuterContext = true;
}
const existing = this.configLookup.add(config);
if (existing === config) {
this.cachedHashCode = -1;
this.configs.push(config); // track order here
return true;
}
// a previous (s,i,pi,_), merge with it and save result
const rootIsWildcard = !this.fullCtx;
const merged = merge(existing.context, config.context, rootIsWildcard, mergeCache);
/**
* no need to check for existing.context, config.context in cache
* since only way to create new graphs is "call rule" and here. We
* cache at both places
*/
existing.reachesIntoOuterContext = Math.max( existing.reachesIntoOuterContext, config.reachesIntoOuterContext);
// make sure to preserve the precedence filter suppression during the merge
if (config.precedenceFilterSuppressed) {
existing.precedenceFilterSuppressed = true;
}
existing.context = merged; // replace context; no need to alt mapping
return true; return true;
} }
// a previous (s,i,pi,_), merge with it and save result
var rootIsWildcard = !this.fullCtx;
var merged = merge(existing.context, config.context, rootIsWildcard, mergeCache);
// no need to check for existing.context, config.context in cache
// since only way to create new graphs is "call rule" and here. We
// cache at both places.
existing.reachesIntoOuterContext = Math.max( existing.reachesIntoOuterContext, config.reachesIntoOuterContext);
// make sure to preserve the precedence filter suppression during the merge
if (config.precedenceFilterSuppressed) {
existing.precedenceFilterSuppressed = true;
}
existing.context = merged; // replace context; no need to alt mapping
return true;
};
ATNConfigSet.prototype.getStates = function() { getStates() {
var states = new Set(); const states = new Utils.Set();
for (var i = 0; i < this.configs.length; i++) { for (let i = 0; i < this.configs.length; i++) {
states.add(this.configs[i].state); states.add(this.configs[i].state);
}
return states;
} }
return states;
};
ATNConfigSet.prototype.getPredicates = function() { getPredicates() {
var preds = []; const preds = [];
for (var i = 0; i < this.configs.length; i++) { for (let i = 0; i < this.configs.length; i++) {
var c = this.configs[i].semanticContext; const c = this.configs[i].semanticContext;
if (c !== SemanticContext.NONE) { if (c !== SemanticContext.NONE) {
preds.push(c.semanticContext); preds.push(c.semanticContext);
}
}
return preds;
}
optimizeConfigs(interpreter) {
if (this.readOnly) {
throw "This set is readonly";
}
if (this.configLookup.length === 0) {
return;
}
for (let i = 0; i < this.configs.length; i++) {
const config = this.configs[i];
config.context = interpreter.getCachedContext(config.context);
} }
} }
return preds;
};
Object.defineProperty(ATNConfigSet.prototype, "items", { addAll(coll) {
get : function() { for (let i = 0; i < coll.length; i++) {
this.add(coll[i]);
}
return false;
}
equals(other) {
return this === other ||
(other instanceof ATNConfigSet &&
Utils.equalArrays(this.configs, other.configs) &&
this.fullCtx === other.fullCtx &&
this.uniqueAlt === other.uniqueAlt &&
this.conflictingAlts === other.conflictingAlts &&
this.hasSemanticContext === other.hasSemanticContext &&
this.dipsIntoOuterContext === other.dipsIntoOuterContext);
}
hashCode() {
const hash = new Utils.Hash();
hash.update(this.configs);
return hash.finish();
}
updateHashCode(hash) {
if (this.readOnly) {
if (this.cachedHashCode === -1) {
this.cachedHashCode = this.hashCode();
}
hash.update(this.cachedHashCode);
} else {
hash.update(this.hashCode());
}
}
isEmpty() {
return this.configs.length === 0;
}
contains(item) {
if (this.configLookup === null) {
throw "This method is not implemented for readonly sets.";
}
return this.configLookup.contains(item);
}
containsFast(item) {
if (this.configLookup === null) {
throw "This method is not implemented for readonly sets.";
}
return this.configLookup.containsFast(item);
}
clear() {
if (this.readOnly) {
throw "This set is readonly";
}
this.configs = [];
this.cachedHashCode = -1;
this.configLookup = new Utils.Set();
}
setReadonly(readOnly) {
this.readOnly = readOnly;
if (readOnly) {
this.configLookup = null; // can't mod, no need for lookup cache
}
}
toString() {
return Utils.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" : "");
}
get items(){
return this.configs; return this.configs;
} }
});
ATNConfigSet.prototype.optimizeConfigs = function(interpreter) { get length(){
if (this.readOnly) {
throw "This set is readonly";
}
if (this.configLookup.length === 0) {
return;
}
for (var i = 0; i < this.configs.length; i++) {
var config = this.configs[i];
config.context = interpreter.getCachedContext(config.context);
}
};
ATNConfigSet.prototype.addAll = function(coll) {
for (var i = 0; i < coll.length; i++) {
this.add(coll[i]);
}
return false;
};
ATNConfigSet.prototype.equals = function(other) {
return this === other ||
(other instanceof ATNConfigSet &&
Utils.equalArrays(this.configs, other.configs) &&
this.fullCtx === other.fullCtx &&
this.uniqueAlt === other.uniqueAlt &&
this.conflictingAlts === other.conflictingAlts &&
this.hasSemanticContext === other.hasSemanticContext &&
this.dipsIntoOuterContext === other.dipsIntoOuterContext);
};
ATNConfigSet.prototype.hashCode = function() {
var hash = new Hash();
hash.update(this.configs);
return hash.finish();
};
ATNConfigSet.prototype.updateHashCode = function(hash) {
if (this.readOnly) {
if (this.cachedHashCode === -1) {
this.cachedHashCode = this.hashCode();
}
hash.update(this.cachedHashCode);
} else {
hash.update(this.hashCode());
}
};
Object.defineProperty(ATNConfigSet.prototype, "length", {
get : function() {
return this.configs.length; return this.configs.length;
} }
});
ATNConfigSet.prototype.isEmpty = function() {
return this.configs.length === 0;
};
ATNConfigSet.prototype.contains = function(item) {
if (this.configLookup === null) {
throw "This method is not implemented for readonly sets.";
}
return this.configLookup.contains(item);
};
ATNConfigSet.prototype.containsFast = function(item) {
if (this.configLookup === null) {
throw "This method is not implemented for readonly sets.";
}
return this.configLookup.containsFast(item);
};
ATNConfigSet.prototype.clear = function() {
if (this.readOnly) {
throw "This set is readonly";
}
this.configs = [];
this.cachedHashCode = -1;
this.configLookup = new Set();
};
ATNConfigSet.prototype.setReadonly = function(readOnly) {
this.readOnly = readOnly;
if (readOnly) {
this.configLookup = null; // can't mod, no need for lookup cache
}
};
ATNConfigSet.prototype.toString = function() {
return Utils.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" : "");
};
function OrderedATNConfigSet() {
ATNConfigSet.call(this);
this.configLookup = new Set();
return this;
} }
OrderedATNConfigSet.prototype = Object.create(ATNConfigSet.prototype);
OrderedATNConfigSet.prototype.constructor = OrderedATNConfigSet;
exports.ATNConfigSet = ATNConfigSet; class OrderedATNConfigSet extends ATNConfigSet {
exports.OrderedATNConfigSet = OrderedATNConfigSet; constructor() {
super();
this.configLookup = new Utils.Set();
}
}
module.exports = {
ATNConfigSet,
OrderedATNConfigSet
}

View File

@ -3,15 +3,15 @@
* can be found in the LICENSE.txt file in the project root. * can be found in the LICENSE.txt file in the project root.
*/ */
function ATNDeserializationOptions(copyFrom) { class ATNDeserializationOptions {
if(copyFrom===undefined) { constructor(copyFrom) {
copyFrom = null; if(copyFrom===undefined) {
copyFrom = null;
}
this.readOnly = false;
this.verifyATN = copyFrom===null ? true : copyFrom.verifyATN;
this.generateRuleBypassTransitions = copyFrom===null ? false : copyFrom.generateRuleBypassTransitions;
} }
this.readOnly = false;
this.verifyATN = copyFrom===null ? true : copyFrom.verifyATN;
this.generateRuleBypassTransitions = copyFrom===null ? false : copyFrom.generateRuleBypassTransitions;
return this;
} }
ATNDeserializationOptions.defaultOptions = new ATNDeserializationOptions(); ATNDeserializationOptions.defaultOptions = new ATNDeserializationOptions();
@ -22,4 +22,4 @@ ATNDeserializationOptions.defaultOptions.readOnly = true;
// raise Exception("The object is read only.") // raise Exception("The object is read only.")
// super(type(self), self).__setattr__(key,value) // super(type(self), self).__setattr__(key,value)
exports.ATNDeserializationOptions = ATNDeserializationOptions; module.exports = ATNDeserializationOptions

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +1,52 @@
//
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
///
var DFAState = require('./../dfa/DFAState').DFAState; const {DFAState} = require('./../dfa/DFAState');
var ATNConfigSet = require('./ATNConfigSet').ATNConfigSet; const {ATNConfigSet} = require('./ATNConfigSet');
var getCachedPredictionContext = require('./../PredictionContext').getCachedPredictionContext; const {getCachedPredictionContext} = require('./../PredictionContext');
var Map = require('./../Utils').Map; const {Map} = require('./../Utils');
function ATNSimulator(atn, sharedContextCache) { class ATNSimulator {
constructor(atn, sharedContextCache) {
/**
* 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().
*
* <p>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.</p>
*
* <p>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.</p>
*/
this.atn = atn;
this.sharedContextCache = sharedContextCache;
return this;
}
// The context cache maps all PredictionContext objects that are == getCachedContext(context) {
// to a single cached copy. This cache is shared across all contexts if (this.sharedContextCache ===null) {
// in all ATNConfigs in all DFA states. We rebuild each ATNConfigSet return context;
// to use only cached nodes/graphs in addDFAState(). We don't want to }
// fill this during closure() since there are lots of contexts that const visited = new Map();
// pop up but are not used ever again. It also greatly slows down closure(). return getCachedPredictionContext(context, this.sharedContextCache, visited);
// }
// <p>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.</p>
//
// <p>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.</p>
///
this.atn = atn;
this.sharedContextCache = sharedContextCache;
return this;
} }
// Must distinguish between missing edge and edge we know leads nowhere/// // Must distinguish between missing edge and edge we know leads nowhere///
ATNSimulator.ERROR = new DFAState(0x7FFFFFFF, new ATNConfigSet()); ATNSimulator.ERROR = new DFAState(0x7FFFFFFF, new ATNConfigSet());
ATNSimulator.prototype.getCachedContext = function(context) { module.exports = ATNSimulator;
if (this.sharedContextCache ===null) {
return context;
}
var visited = new Map();
return getCachedPredictionContext(context, this.sharedContextCache, visited);
};
exports.ATNSimulator = ATNSimulator;

View File

@ -1,84 +1,115 @@
//
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
//
// The following images show the relation of states and const INITIAL_NUM_TRANSITIONS = 4;
// {@link ATNState//transitions} for various grammar constructs.
//
// <ul>
//
// <li>Solid edges marked with an &//0949; indicate a required
// {@link EpsilonTransition}.</li>
//
// <li>Dashed edges indicate locations where any transition derived from
// {@link Transition} might appear.</li>
//
// <li>Dashed nodes are place holders for either a sequence of linked
// {@link BasicState} states or the inclusion of a block representing a nested
// construct in one of the forms below.</li>
//
// <li>Nodes showing multiple outgoing alternatives with a {@code ...} support
// any number of alternatives (one or more). Nodes without the {@code ...} only
// support the exact number of alternatives shown in the diagram.</li>
//
// </ul>
//
// <h2>Basic Blocks</h2>
//
// <h3>Rule</h3>
//
// <embed src="images/Rule.svg" type="image/svg+xml"/>
//
// <h3>Block of 1 or more alternatives</h3>
//
// <embed src="images/Block.svg" type="image/svg+xml"/>
//
// <h2>Greedy Loops</h2>
//
// <h3>Greedy Closure: {@code (...)*}</h3>
//
// <embed src="images/ClosureGreedy.svg" type="image/svg+xml"/>
//
// <h3>Greedy Positive Closure: {@code (...)+}</h3>
//
// <embed src="images/PositiveClosureGreedy.svg" type="image/svg+xml"/>
//
// <h3>Greedy Optional: {@code (...)?}</h3>
//
// <embed src="images/OptionalGreedy.svg" type="image/svg+xml"/>
//
// <h2>Non-Greedy Loops</h2>
//
// <h3>Non-Greedy Closure: {@code (...)*?}</h3>
//
// <embed src="images/ClosureNonGreedy.svg" type="image/svg+xml"/>
//
// <h3>Non-Greedy Positive Closure: {@code (...)+?}</h3>
//
// <embed src="images/PositiveClosureNonGreedy.svg" type="image/svg+xml"/>
//
// <h3>Non-Greedy Optional: {@code (...)??}</h3>
//
// <embed src="images/OptionalNonGreedy.svg" type="image/svg+xml"/>
//
var INITIAL_NUM_TRANSITIONS = 4; /**
* The following images show the relation of states and
* {@link ATNState//transitions} for various grammar constructs.
*
* <ul>
*
* <li>Solid edges marked with an &//0949; indicate a required
* {@link EpsilonTransition}.</li>
*
* <li>Dashed edges indicate locations where any transition derived from
* {@link Transition} might appear.</li>
*
* <li>Dashed nodes are place holders for either a sequence of linked
* {@link BasicState} states or the inclusion of a block representing a nested
* construct in one of the forms below.</li>
*
* <li>Nodes showing multiple outgoing alternatives with a {@code ...} support
* any number of alternatives (one or more). Nodes without the {@code ...} only
* support the exact number of alternatives shown in the diagram.</li>
*
* </ul>
*
* <h2>Basic Blocks</h2>
*
* <h3>Rule</h3>
*
* <embed src="images/Rule.svg" type="image/svg+xml"/>
*
* <h3>Block of 1 or more alternatives</h3>
*
* <embed src="images/Block.svg" type="image/svg+xml"/>
*
* <h2>Greedy Loops</h2>
*
* <h3>Greedy Closure: {@code (...)*}</h3>
*
* <embed src="images/ClosureGreedy.svg" type="image/svg+xml"/>
*
* <h3>Greedy Positive Closure: {@code (...)+}</h3>
*
* <embed src="images/PositiveClosureGreedy.svg" type="image/svg+xml"/>
*
* <h3>Greedy Optional: {@code (...)?}</h3>
*
* <embed src="images/OptionalGreedy.svg" type="image/svg+xml"/>
*
* <h2>Non-Greedy Loops</h2>
*
* <h3>Non-Greedy Closure: {@code (...)*?}</h3>
*
* <embed src="images/ClosureNonGreedy.svg" type="image/svg+xml"/>
*
* <h3>Non-Greedy Positive Closure: {@code (...)+?}</h3>
*
* <embed src="images/PositiveClosureNonGreedy.svg" type="image/svg+xml"/>
*
* <h3>Non-Greedy Optional: {@code (...)??}</h3>
*
* <embed src="images/OptionalNonGreedy.svg" type="image/svg+xml"/>
*/
class ATNState {
constructor() {
// Which ATN are we in?
this.atn = null;
this.stateNumber = ATNState.INVALID_STATE_NUMBER;
this.stateType = null;
this.ruleIndex = 0; // at runtime, we don't have Rule objects
this.epsilonOnlyTransitions = false;
// Track the transitions emanating from this ATN state.
this.transitions = [];
// Used to cache lookahead during parsing, not used during construction
this.nextTokenWithinRule = null;
}
function ATNState() { toString() {
// Which ATN are we in? return this.stateNumber;
this.atn = null; }
this.stateNumber = ATNState.INVALID_STATE_NUMBER;
this.stateType = null; equals(other) {
this.ruleIndex = 0; // at runtime, we don't have Rule objects if (other instanceof ATNState) {
this.epsilonOnlyTransitions = false; return this.stateNumber===other.stateNumber;
// Track the transitions emanating from this ATN state. } else {
this.transitions = []; return false;
// Used to cache lookahead during parsing, not used during construction }
this.nextTokenWithinRule = null; }
return this;
isNonGreedyExitState() {
return false;
}
addTransition(trans, index) {
if(index===undefined) {
index = -1;
}
if (this.transitions.length===0) {
this.epsilonOnlyTransitions = trans.isEpsilon;
} else if(this.epsilonOnlyTransitions !== trans.isEpsilon) {
this.epsilonOnlyTransitions = false;
}
if (index===-1) {
this.transitions.push(trans);
} else {
this.transitions.splice(index, 1, trans);
}
}
} }
// constants for serialization // constants for serialization
@ -113,214 +144,172 @@ ATNState.serializationNames = [
ATNState.INVALID_STATE_NUMBER = -1; ATNState.INVALID_STATE_NUMBER = -1;
ATNState.prototype.toString = function() {
return this.stateNumber;
};
ATNState.prototype.equals = function(other) { class BasicState extends ATNState {
if (other instanceof ATNState) { constructor() {
return this.stateNumber===other.stateNumber; super();
} else { this.stateType = ATNState.BASIC;
return false;
} }
}; }
ATNState.prototype.isNonGreedyExitState = function() { class DecisionState extends ATNState {
return false; constructor() {
}; super();
this.decision = -1;
this.nonGreedy = false;
ATNState.prototype.addTransition = function(trans, index) { return this;
if(index===undefined) {
index = -1;
}
if (this.transitions.length===0) {
this.epsilonOnlyTransitions = trans.isEpsilon;
} else if(this.epsilonOnlyTransitions !== trans.isEpsilon) {
this.epsilonOnlyTransitions = false;
} }
if (index===-1) { }
this.transitions.push(trans);
} else { /**
this.transitions.splice(index, 1, trans); * The start of a regular {@code (...)} block
*/
class BlockStartState extends DecisionState {
constructor() {
super();
this.endState = null;
return this;
} }
};
function BasicState() {
ATNState.call(this);
this.stateType = ATNState.BASIC;
return this;
} }
BasicState.prototype = Object.create(ATNState.prototype); class BasicBlockStartState extends BlockStartState {
BasicState.prototype.constructor = BasicState; constructor() {
super();
this.stateType = ATNState.BLOCK_START;
function DecisionState() { return this;
ATNState.call(this); }
this.decision = -1;
this.nonGreedy = false;
return this;
} }
DecisionState.prototype = Object.create(ATNState.prototype); /**
DecisionState.prototype.constructor = DecisionState; * Terminal node of a simple {@code (a|b|c)} block
*/
class BlockEndState extends ATNState {
// The start of a regular {@code (...)} block. constructor() {
function BlockStartState() { super();
DecisionState.call(this); this.stateType = ATNState.BLOCK_END;
this.endState = null; this.startState = null;
return this; return this;
}
} }
BlockStartState.prototype = Object.create(DecisionState.prototype); /**
BlockStartState.prototype.constructor = BlockStartState; * The last node in the ATN for a rule, unless that rule is the start symbol.
* In that case, there is one transition to EOF. Later, we might encode
* references to all calls to this rule to compute FOLLOW sets for
function BasicBlockStartState() { * error handling
BlockStartState.call(this); */
this.stateType = ATNState.BLOCK_START; class RuleStopState extends ATNState {
return this; constructor() {
super();
this.stateType = ATNState.RULE_STOP;
return this;
}
} }
BasicBlockStartState.prototype = Object.create(BlockStartState.prototype); class RuleStartState extends ATNState {
BasicBlockStartState.prototype.constructor = BasicBlockStartState; constructor() {
super();
this.stateType = ATNState.RULE_START;
// Terminal node of a simple {@code (a|b|c)} block. this.stopState = null;
function BlockEndState() { this.isPrecedenceRule = false;
ATNState.call(this); return this;
this.stateType = ATNState.BLOCK_END; }
this.startState = null;
return this;
} }
BlockEndState.prototype = Object.create(ATNState.prototype); /**
BlockEndState.prototype.constructor = BlockEndState; * Decision state for {@code A+} and {@code (A|B)+}. It has two transitions:
* one to the loop back to start of the block and one to exit.
*/
// The last node in the ATN for a rule, unless that rule is the start symbol. class PlusLoopbackState extends DecisionState {
// In that case, there is one transition to EOF. Later, we might encode constructor() {
// references to all calls to this rule to compute FOLLOW sets for super();
// error handling. this.stateType = ATNState.PLUS_LOOP_BACK;
// return this;
function RuleStopState() { }
ATNState.call(this);
this.stateType = ATNState.RULE_STOP;
return this;
} }
RuleStopState.prototype = Object.create(ATNState.prototype); /**
RuleStopState.prototype.constructor = RuleStopState; * Start of {@code (A|B|...)+} loop. Technically a decision state, but
* we don't use for code generation; somebody might need it, so I'm defining
function RuleStartState() { * it for completeness. In reality, the {@link PlusLoopbackState} node is the
ATNState.call(this); * real decision-making note for {@code A+}
this.stateType = ATNState.RULE_START; */
this.stopState = null; class PlusBlockStartState extends BlockStartState {
this.isPrecedenceRule = false; constructor() {
return this; super();
this.stateType = ATNState.PLUS_BLOCK_START;
this.loopBackState = null;
return this;
}
} }
RuleStartState.prototype = Object.create(ATNState.prototype); /**
RuleStartState.prototype.constructor = RuleStartState; * The block that begins a closure loop
*/
// Decision state for {@code A+} and {@code (A|B)+}. It has two transitions: class StarBlockStartState extends BlockStartState {
// one to the loop back to start of the block and one to exit. constructor() {
// super();
function PlusLoopbackState() { this.stateType = ATNState.STAR_BLOCK_START;
DecisionState.call(this); return this;
this.stateType = ATNState.PLUS_LOOP_BACK; }
return this;
} }
PlusLoopbackState.prototype = Object.create(DecisionState.prototype); class StarLoopbackState extends ATNState {
PlusLoopbackState.prototype.constructor = PlusLoopbackState; constructor() {
super();
this.stateType = ATNState.STAR_LOOP_BACK;
// Start of {@code (A|B|...)+} loop. Technically a decision state, but return this;
// we don't use for code generation; somebody might need it, so I'm defining }
// it for completeness. In reality, the {@link PlusLoopbackState} node is the
// real decision-making note for {@code A+}.
//
function PlusBlockStartState() {
BlockStartState.call(this);
this.stateType = ATNState.PLUS_BLOCK_START;
this.loopBackState = null;
return this;
} }
PlusBlockStartState.prototype = Object.create(BlockStartState.prototype); class StarLoopEntryState extends DecisionState {
PlusBlockStartState.prototype.constructor = PlusBlockStartState; constructor() {
super();
// The block that begins a closure loop. this.stateType = ATNState.STAR_LOOP_ENTRY;
function StarBlockStartState() { this.loopBackState = null;
BlockStartState.call(this); // Indicates whether this state can benefit from a precedence DFA during SLL decision making.
this.stateType = ATNState.STAR_BLOCK_START; this.isPrecedenceDecision = null;
return this; return this;
}
} }
StarBlockStartState.prototype = Object.create(BlockStartState.prototype); /**
StarBlockStartState.prototype.constructor = StarBlockStartState; * Mark the end of a * or + loop
*/
class LoopEndState extends ATNState {
function StarLoopbackState() { constructor() {
ATNState.call(this); super();
this.stateType = ATNState.STAR_LOOP_BACK; this.stateType = ATNState.LOOP_END;
return this; this.loopBackState = null;
return this;
}
} }
StarLoopbackState.prototype = Object.create(ATNState.prototype); /**
StarLoopbackState.prototype.constructor = StarLoopbackState; * The Tokens rule start state linking to each lexer rule start state
*/
class TokensStartState extends DecisionState {
function StarLoopEntryState() { constructor() {
DecisionState.call(this); super();
this.stateType = ATNState.STAR_LOOP_ENTRY; this.stateType = ATNState.TOKEN_START;
this.loopBackState = null; return this;
// Indicates whether this state can benefit from a precedence DFA during SLL decision making. }
this.isPrecedenceDecision = null;
return this;
} }
StarLoopEntryState.prototype = Object.create(DecisionState.prototype); module.exports = {
StarLoopEntryState.prototype.constructor = StarLoopEntryState; ATNState,
BasicState,
DecisionState,
// Mark the end of a * or + loop. BlockStartState,
function LoopEndState() { BlockEndState,
ATNState.call(this); LoopEndState,
this.stateType = ATNState.LOOP_END; RuleStartState,
this.loopBackState = null; RuleStopState,
return this; TokensStartState,
PlusLoopbackState,
StarLoopbackState,
StarLoopEntryState,
PlusBlockStartState,
StarBlockStartState,
BasicBlockStartState
} }
LoopEndState.prototype = Object.create(ATNState.prototype);
LoopEndState.prototype.constructor = LoopEndState;
// The Tokens rule start state linking to each lexer rule start state */
function TokensStartState() {
DecisionState.call(this);
this.stateType = ATNState.TOKEN_START;
return this;
}
TokensStartState.prototype = Object.create(DecisionState.prototype);
TokensStartState.prototype.constructor = TokensStartState;
exports.ATNState = ATNState;
exports.BasicState = BasicState;
exports.DecisionState = DecisionState;
exports.BlockStartState = BlockStartState;
exports.BlockEndState = BlockEndState;
exports.LoopEndState = LoopEndState;
exports.RuleStartState = RuleStartState;
exports.RuleStopState = RuleStopState;
exports.TokensStartState = TokensStartState;
exports.PlusLoopbackState = PlusLoopbackState;
exports.StarLoopbackState = StarLoopbackState;
exports.StarLoopEntryState = StarLoopEntryState;
exports.PlusBlockStartState = PlusBlockStartState;
exports.StarBlockStartState = StarBlockStartState;
exports.BasicBlockStartState = BasicBlockStartState;

View File

@ -2,16 +2,12 @@
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
///
// Represents the type of recognizer an ATN applies to. /**
* Represents the type of recognizer an ATN applies to
function ATNType() { */
module.exports = {
} LEXER: 0,
PARSER: 1
ATNType.LEXER = 0; };
ATNType.PARSER = 1;
exports.ATNType = ATNType;

File diff suppressed because it is too large Load Diff

View File

@ -1,366 +1,384 @@
//
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
//
function LexerActionType() { const LexerActionType = {
// The type of a {@link LexerChannelAction} action.
CHANNEL: 0,
// The type of a {@link LexerCustomAction} action
CUSTOM: 1,
// The type of a {@link LexerModeAction} action.
MODE: 2,
//The type of a {@link LexerMoreAction} action.
MORE: 3,
//The type of a {@link LexerPopModeAction} action.
POP_MODE: 4,
//The type of a {@link LexerPushModeAction} action.
PUSH_MODE: 5,
//The type of a {@link LexerSkipAction} action.
SKIP: 6,
//The type of a {@link LexerTypeAction} action.
TYPE: 7
} }
LexerActionType.CHANNEL = 0; //The type of a {@link LexerChannelAction} action. class LexerAction {
LexerActionType.CUSTOM = 1; //The type of a {@link LexerCustomAction} action. constructor(action) {
LexerActionType.MODE = 2; //The type of a {@link LexerModeAction} action. this.actionType = action;
LexerActionType.MORE = 3; //The type of a {@link LexerMoreAction} action. this.isPositionDependent = false;
LexerActionType.POP_MODE = 4; //The type of a {@link LexerPopModeAction} action. }
LexerActionType.PUSH_MODE = 5; //The type of a {@link LexerPushModeAction} action.
LexerActionType.SKIP = 6; //The type of a {@link LexerSkipAction} action.
LexerActionType.TYPE = 7; //The type of a {@link LexerTypeAction} action.
function LexerAction(action) { hashCode() {
this.actionType = action; const hash = new Hash();
this.isPositionDependent = false; this.updateHashCode(hash);
return this; return hash.finish()
}
updateHashCode(hash) {
hash.update(this.actionType);
}
equals(other) {
return this === other;
}
} }
LexerAction.prototype.hashCode = function() {
var hash = new Hash();
this.updateHashCode(hash);
return hash.finish()
};
LexerAction.prototype.updateHashCode = function(hash) { /**
hash.update(this.actionType); * Implements the {@code skip} lexer action by calling {@link Lexer//skip}.
}; *
* <p>The {@code skip} command does not have any parameters, so this action is
* implemented as a singleton instance exposed by {@link //INSTANCE}.</p>
*/
class LexerSkipAction extends LexerAction {
constructor() {
super(LexerActionType.SKIP);
}
LexerAction.prototype.equals = function(other) { execute(lexer) {
return this === other; lexer.skip();
}; }
toString() {
return "skip";
// }
// Implements the {@code skip} lexer action by calling {@link Lexer//skip}.
//
// <p>The {@code skip} command does not have any parameters, so this action is
// implemented as a singleton instance exposed by {@link //INSTANCE}.</p>
function LexerSkipAction() {
LexerAction.call(this, LexerActionType.SKIP);
return this;
} }
LexerSkipAction.prototype = Object.create(LexerAction.prototype);
LexerSkipAction.prototype.constructor = LexerSkipAction;
// Provides a singleton instance of this parameterless lexer action. // Provides a singleton instance of this parameterless lexer action.
LexerSkipAction.INSTANCE = new LexerSkipAction(); LexerSkipAction.INSTANCE = new LexerSkipAction();
LexerSkipAction.prototype.execute = function(lexer) { /**
lexer.skip(); * Implements the {@code type} lexer action by calling {@link Lexer//setType}
}; * with the assigned type
*/
LexerSkipAction.prototype.toString = function() { class LexerTypeAction extends LexerAction {
return "skip"; constructor(type) {
}; super(LexerActionType.TYPE);
this.type = type;
// Implements the {@code type} lexer action by calling {@link Lexer//setType}
// with the assigned type.
function LexerTypeAction(type) {
LexerAction.call(this, LexerActionType.TYPE);
this.type = type;
return this;
}
LexerTypeAction.prototype = Object.create(LexerAction.prototype);
LexerTypeAction.prototype.constructor = LexerTypeAction;
LexerTypeAction.prototype.execute = function(lexer) {
lexer.type = this.type;
};
LexerTypeAction.prototype.updateHashCode = function(hash) {
hash.update(this.actionType, this.type);
};
LexerTypeAction.prototype.equals = function(other) {
if(this === other) {
return true;
} else if (! (other instanceof LexerTypeAction)) {
return false;
} else {
return this.type === other.type;
} }
};
LexerTypeAction.prototype.toString = function() { execute(lexer) {
return "type(" + this.type + ")"; lexer.type = this.type;
};
// Implements the {@code pushMode} lexer action by calling
// {@link Lexer//pushMode} with the assigned mode.
function LexerPushModeAction(mode) {
LexerAction.call(this, LexerActionType.PUSH_MODE);
this.mode = mode;
return this;
}
LexerPushModeAction.prototype = Object.create(LexerAction.prototype);
LexerPushModeAction.prototype.constructor = LexerPushModeAction;
// <p>This action is implemented by calling {@link Lexer//pushMode} with the
// value provided by {@link //getMode}.</p>
LexerPushModeAction.prototype.execute = function(lexer) {
lexer.pushMode(this.mode);
};
LexerPushModeAction.prototype.updateHashCode = function(hash) {
hash.update(this.actionType, this.mode);
};
LexerPushModeAction.prototype.equals = function(other) {
if (this === other) {
return true;
} else if (! (other instanceof LexerPushModeAction)) {
return false;
} else {
return this.mode === other.mode;
} }
};
LexerPushModeAction.prototype.toString = function() { updateHashCode(hash) {
return "pushMode(" + this.mode + ")"; hash.update(this.actionType, this.type);
}; }
equals(other) {
if(this === other) {
return true;
} else if (! (other instanceof LexerTypeAction)) {
return false;
} else {
return this.type === other.type;
}
}
// Implements the {@code popMode} lexer action by calling {@link Lexer//popMode}. toString() {
// return "type(" + this.type + ")";
// <p>The {@code popMode} command does not have any parameters, so this action is }
// implemented as a singleton instance exposed by {@link //INSTANCE}.</p>
function LexerPopModeAction() {
LexerAction.call(this,LexerActionType.POP_MODE);
return this;
} }
LexerPopModeAction.prototype = Object.create(LexerAction.prototype);
LexerPopModeAction.prototype.constructor = LexerPopModeAction; /**
* Implements the {@code pushMode} lexer action by calling
* {@link Lexer//pushMode} with the assigned mode
*/
class LexerPushModeAction extends LexerAction {
constructor(mode) {
super(LexerActionType.PUSH_MODE);
this.mode = mode;
}
/**
* <p>This action is implemented by calling {@link Lexer//pushMode} with the
* value provided by {@link //getMode}.</p>
*/
execute(lexer) {
lexer.pushMode(this.mode);
}
updateHashCode(hash) {
hash.update(this.actionType, this.mode);
}
equals(other) {
if (this === other) {
return true;
} else if (! (other instanceof LexerPushModeAction)) {
return false;
} else {
return this.mode === other.mode;
}
}
toString() {
return "pushMode(" + this.mode + ")";
}
}
/**
* Implements the {@code popMode} lexer action by calling {@link Lexer//popMode}.
*
* <p>The {@code popMode} command does not have any parameters, so this action is
* implemented as a singleton instance exposed by {@link //INSTANCE}.</p>
*/
class LexerPopModeAction extends LexerAction {
constructor() {
super(LexerActionType.POP_MODE);
}
/**
* <p>This action is implemented by calling {@link Lexer//popMode}.</p>
*/
execute(lexer) {
lexer.popMode();
}
toString() {
return "popMode";
}
}
LexerPopModeAction.INSTANCE = new LexerPopModeAction(); LexerPopModeAction.INSTANCE = new LexerPopModeAction();
// <p>This action is implemented by calling {@link Lexer//popMode}.</p> /**
LexerPopModeAction.prototype.execute = function(lexer) { * Implements the {@code more} lexer action by calling {@link Lexer//more}.
lexer.popMode(); *
}; * <p>The {@code more} command does not have any parameters, so this action is
* implemented as a singleton instance exposed by {@link //INSTANCE}.</p>
*/
class LexerMoreAction extends LexerAction {
constructor() {
super(LexerActionType.MORE);
}
LexerPopModeAction.prototype.toString = function() { /**
return "popMode"; * <p>This action is implemented by calling {@link Lexer//popMode}.</p>
}; */
execute(lexer) {
lexer.more();
}
// Implements the {@code more} lexer action by calling {@link Lexer//more}. toString() {
// return "more";
// <p>The {@code more} command does not have any parameters, so this action is }
// implemented as a singleton instance exposed by {@link //INSTANCE}.</p>
function LexerMoreAction() {
LexerAction.call(this, LexerActionType.MORE);
return this;
} }
LexerMoreAction.prototype = Object.create(LexerAction.prototype);
LexerMoreAction.prototype.constructor = LexerMoreAction;
LexerMoreAction.INSTANCE = new LexerMoreAction(); LexerMoreAction.INSTANCE = new LexerMoreAction();
// <p>This action is implemented by calling {@link Lexer//popMode}.</p>
LexerMoreAction.prototype.execute = function(lexer) {
lexer.more();
};
LexerMoreAction.prototype.toString = function() { /**
return "more"; * Implements the {@code mode} lexer action by calling {@link Lexer//mode} with
}; * the assigned mode
*/
class LexerModeAction extends LexerAction {
constructor(mode) {
super(LexerActionType.MODE);
this.mode = mode;
}
/**
* <p>This action is implemented by calling {@link Lexer//mode} with the
* value provided by {@link //getMode}.</p>
*/
execute(lexer) {
lexer.mode(this.mode);
}
// Implements the {@code mode} lexer action by calling {@link Lexer//mode} with updateHashCode(hash) {
// the assigned mode. hash.update(this.actionType, this.mode);
function LexerModeAction(mode) { }
LexerAction.call(this, LexerActionType.MODE);
this.mode = mode; equals(other) {
return this; if (this === other) {
return true;
} else if (! (other instanceof LexerModeAction)) {
return false;
} else {
return this.mode === other.mode;
}
}
toString() {
return "mode(" + this.mode + ")";
}
} }
LexerModeAction.prototype = Object.create(LexerAction.prototype); /**
LexerModeAction.prototype.constructor = LexerModeAction; * Executes a custom lexer action by calling {@link Recognizer//action} with the
* rule and action indexes assigned to the custom action. The implementation of
// <p>This action is implemented by calling {@link Lexer//mode} with the * a custom action is added to the generated code for the lexer in an override
// value provided by {@link //getMode}.</p> * of {@link Recognizer//action} when the grammar is compiled.
LexerModeAction.prototype.execute = function(lexer) { *
lexer.mode(this.mode); * <p>This class may represent embedded actions created with the <code>{...}</code>
}; * syntax in ANTLR 4, as well as actions created for lexer commands where the
* command argument could not be evaluated when the grammar was compiled.</p>
LexerModeAction.prototype.updateHashCode = function(hash) { */
hash.update(this.actionType, this.mode); class LexerCustomAction extends LexerAction {
}; /**
* Constructs a custom lexer action with the specified rule and action
LexerModeAction.prototype.equals = function(other) { * indexes.
if (this === other) { *
return true; * @param ruleIndex The rule index to use for calls to
} else if (! (other instanceof LexerModeAction)) { * {@link Recognizer//action}.
return false; * @param actionIndex The action index to use for calls to
} else { * {@link Recognizer//action}.
return this.mode === other.mode; */
constructor(ruleIndex, actionIndex) {
super(LexerActionType.CUSTOM);
this.ruleIndex = ruleIndex;
this.actionIndex = actionIndex;
this.isPositionDependent = true;
} }
};
LexerModeAction.prototype.toString = function() { /**
return "mode(" + this.mode + ")"; * <p>Custom actions are implemented by calling {@link Lexer//action} with the
}; * appropriate rule and action indexes.</p>
*/
execute(lexer) {
lexer.action(null, this.ruleIndex, this.actionIndex);
}
// Executes a custom lexer action by calling {@link Recognizer//action} with the updateHashCode(hash) {
// rule and action indexes assigned to the custom action. The implementation of hash.update(this.actionType, this.ruleIndex, this.actionIndex);
// a custom action is added to the generated code for the lexer in an override }
// of {@link Recognizer//action} when the grammar is compiled.
//
// <p>This class may represent embedded actions created with the <code>{...}</code>
// syntax in ANTLR 4, as well as actions created for lexer commands where the
// command argument could not be evaluated when the grammar was compiled.</p>
equals(other) {
// Constructs a custom lexer action with the specified rule and action if (this === other) {
// indexes. return true;
// } else if (! (other instanceof LexerCustomAction)) {
// @param ruleIndex The rule index to use for calls to return false;
// {@link Recognizer//action}. } else {
// @param actionIndex The action index to use for calls to return this.ruleIndex === other.ruleIndex && this.actionIndex === other.actionIndex;
// {@link Recognizer//action}. }
}
function LexerCustomAction(ruleIndex, actionIndex) {
LexerAction.call(this, LexerActionType.CUSTOM);
this.ruleIndex = ruleIndex;
this.actionIndex = actionIndex;
this.isPositionDependent = true;
return this;
} }
LexerCustomAction.prototype = Object.create(LexerAction.prototype); /**
LexerCustomAction.prototype.constructor = LexerCustomAction; * Implements the {@code channel} lexer action by calling
* {@link Lexer//setChannel} with the assigned channel.
// <p>Custom actions are implemented by calling {@link Lexer//action} with the * Constructs a new {@code channel} action with the specified channel value.
// appropriate rule and action indexes.</p> * @param channel The channel value to pass to {@link Lexer//setChannel}
LexerCustomAction.prototype.execute = function(lexer) { */
lexer.action(null, this.ruleIndex, this.actionIndex); class LexerChannelAction extends LexerAction {
}; constructor(channel) {
super(LexerActionType.CHANNEL);
LexerCustomAction.prototype.updateHashCode = function(hash) { this.channel = channel;
hash.update(this.actionType, this.ruleIndex, this.actionIndex);
};
LexerCustomAction.prototype.equals = function(other) {
if (this === other) {
return true;
} else if (! (other instanceof LexerCustomAction)) {
return false;
} else {
return this.ruleIndex === other.ruleIndex && this.actionIndex === other.actionIndex;
} }
};
// Implements the {@code channel} lexer action by calling /**
// {@link Lexer//setChannel} with the assigned channel. * <p>This action is implemented by calling {@link Lexer//setChannel} with the
// Constructs a new {@code channel} action with the specified channel value. * value provided by {@link //getChannel}.</p>
// @param channel The channel value to pass to {@link Lexer//setChannel}. */
function LexerChannelAction(channel) { execute(lexer) {
LexerAction.call(this, LexerActionType.CHANNEL); lexer._channel = this.channel;
this.channel = channel; }
return this;
updateHashCode(hash) {
hash.update(this.actionType, this.channel);
}
equals(other) {
if (this === other) {
return true;
} else if (! (other instanceof LexerChannelAction)) {
return false;
} else {
return this.channel === other.channel;
}
}
toString() {
return "channel(" + this.channel + ")";
}
} }
LexerChannelAction.prototype = Object.create(LexerAction.prototype);
LexerChannelAction.prototype.constructor = LexerChannelAction;
// <p>This action is implemented by calling {@link Lexer//setChannel} with the /**
// value provided by {@link //getChannel}.</p> * This implementation of {@link LexerAction} is used for tracking input offsets
LexerChannelAction.prototype.execute = function(lexer) { * for position-dependent actions within a {@link LexerActionExecutor}.
lexer._channel = this.channel; *
}; * <p>This action is not serialized as part of the ATN, and is only required for
* position-dependent lexer actions which appear at a location other than the
LexerChannelAction.prototype.updateHashCode = function(hash) { * end of a rule. For more information about DFA optimizations employed for
hash.update(this.actionType, this.channel); * lexer actions, see {@link LexerActionExecutor//append} and
}; * {@link LexerActionExecutor//fixOffsetBeforeMatch}.</p>
*
LexerChannelAction.prototype.equals = function(other) { * Constructs a new indexed custom action by associating a character offset
if (this === other) { * with a {@link LexerAction}.
return true; *
} else if (! (other instanceof LexerChannelAction)) { * <p>Note: This class is only required for lexer actions for which
return false; * {@link LexerAction//isPositionDependent} returns {@code true}.</p>
} else { *
return this.channel === other.channel; * @param offset The offset into the input {@link CharStream}, relative to
* the token start index, at which the specified lexer action should be
* executed.
* @param action The lexer action to execute at a particular offset in the
* input {@link CharStream}.
*/
class LexerIndexedCustomAction extends LexerAction {
constructor(offset, action) {
super(action.actionType);
this.offset = offset;
this.action = action;
this.isPositionDependent = true;
} }
};
LexerChannelAction.prototype.toString = function() { /**
return "channel(" + this.channel + ")"; * <p>This method calls {@link //execute} on the result of {@link //getAction}
}; * using the provided {@code lexer}.</p>
*/
execute(lexer) {
// assume the input stream position was properly set by the calling code
this.action.execute(lexer);
}
// This implementation of {@link LexerAction} is used for tracking input offsets updateHashCode(hash) {
// for position-dependent actions within a {@link LexerActionExecutor}. hash.update(this.actionType, this.offset, this.action);
// }
// <p>This action is not serialized as part of the ATN, and is only required for
// position-dependent lexer actions which appear at a location other than the
// end of a rule. For more information about DFA optimizations employed for
// lexer actions, see {@link LexerActionExecutor//append} and
// {@link LexerActionExecutor//fixOffsetBeforeMatch}.</p>
// Constructs a new indexed custom action by associating a character offset equals(other) {
// with a {@link LexerAction}. if (this === other) {
// return true;
// <p>Note: This class is only required for lexer actions for which } else if (! (other instanceof LexerIndexedCustomAction)) {
// {@link LexerAction//isPositionDependent} returns {@code true}.</p> return false;
// } else {
// @param offset The offset into the input {@link CharStream}, relative to return this.offset === other.offset && this.action === other.action;
// the token start index, at which the specified lexer action should be }
// executed. }
// @param action The lexer action to execute at a particular offset in the
// input {@link CharStream}.
function LexerIndexedCustomAction(offset, action) {
LexerAction.call(this, action.actionType);
this.offset = offset;
this.action = action;
this.isPositionDependent = true;
return this;
} }
LexerIndexedCustomAction.prototype = Object.create(LexerAction.prototype); module.exports = {
LexerIndexedCustomAction.prototype.constructor = LexerIndexedCustomAction; LexerActionType,
LexerSkipAction,
// <p>This method calls {@link //execute} on the result of {@link //getAction} LexerChannelAction,
// using the provided {@code lexer}.</p> LexerCustomAction,
LexerIndexedCustomAction.prototype.execute = function(lexer) { LexerIndexedCustomAction,
// assume the input stream position was properly set by the calling code LexerMoreAction,
this.action.execute(lexer); LexerTypeAction,
}; LexerPushModeAction,
LexerPopModeAction,
LexerIndexedCustomAction.prototype.updateHashCode = function(hash) { LexerModeAction
hash.update(this.actionType, this.offset, this.action); }
};
LexerIndexedCustomAction.prototype.equals = function(other) {
if (this === other) {
return true;
} else if (! (other instanceof LexerIndexedCustomAction)) {
return false;
} else {
return this.offset === other.offset && this.action === other.action;
}
};
exports.LexerActionType = LexerActionType;
exports.LexerSkipAction = LexerSkipAction;
exports.LexerChannelAction = LexerChannelAction;
exports.LexerCustomAction = LexerCustomAction;
exports.LexerIndexedCustomAction = LexerIndexedCustomAction;
exports.LexerMoreAction = LexerMoreAction;
exports.LexerTypeAction = LexerTypeAction;
exports.LexerPushModeAction = LexerPushModeAction;
exports.LexerPopModeAction = LexerPopModeAction;
exports.LexerModeAction = LexerModeAction;

View File

@ -1,166 +1,173 @@
//
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
///
// Represents an executor for a sequence of lexer actions which traversed during const {hashStuff} = require("../Utils");
// the matching operation of a lexer rule (token). const {LexerIndexedCustomAction} = require('./LexerAction');
//
// <p>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.</p>
var hashStuff = require("../Utils").hashStuff; class LexerActionExecutor {
var LexerIndexedCustomAction = require('./LexerAction').LexerIndexedCustomAction; /**
* Represents an executor for a sequence of lexer actions which traversed during
* the matching operation of a lexer rule (token).
*
* <p>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.</p>
*/
constructor(lexerActions) {
this.lexerActions = lexerActions === null ? [] : lexerActions;
/**
* Caches the result of {@link //hashCode} since the hash code is an element
* of the performance-critical {@link LexerATNConfig//hashCode} operation
*/
this.cachedHashCode = hashStuff(lexerActions); // "".join([str(la) for la in
// lexerActions]))
return this;
}
function LexerActionExecutor(lexerActions) { /**
this.lexerActions = lexerActions === null ? [] : lexerActions; * Creates a {@link LexerActionExecutor} which encodes the current offset
// Caches the result of {@link //hashCode} since the hash code is an element * for position-dependent lexer actions.
// of the performance-critical {@link LexerATNConfig//hashCode} operation. *
this.cachedHashCode = hashStuff(lexerActions); // "".join([str(la) for la in * <p>Normally, when the executor encounters lexer actions where
// lexerActions])) * {@link LexerAction//isPositionDependent} returns {@code true}, it calls
return this; * {@link IntStream//seek} on the input {@link CharStream} to set the input
* position to the <em>end</em> 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.</p>
*
* <p>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.</p>
*
* <p>If the current executor already has offsets assigned to all
* position-dependent lexer actions, the method returns {@code this}.</p>
*
* @param offset The current offset to assign to all position-dependent
* lexer actions which do not already have offsets assigned.
*
* @return {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}.
*
* <p>This method calls {@link IntStream//seek} to set the position of the
* {@code 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.</p>
*
* @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
* {@code 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 {@code input} position to the beginning
* of the token.
*/
execute(lexer, input, startIndex) {
let requiresSeek = false;
const stopIndex = input.index;
try {
for (let i = 0; i < this.lexerActions.length; i++) {
let lexerAction = this.lexerActions[i];
if (lexerAction instanceof LexerIndexedCustomAction) {
const offset = lexerAction.offset;
input.seek(startIndex + offset);
lexerAction = lexerAction.action;
requiresSeek = (startIndex + offset) !== stopIndex;
} else if (lexerAction.isPositionDependent) {
input.seek(stopIndex);
requiresSeek = false;
}
lexerAction.execute(lexer);
}
} finally {
if (requiresSeek) {
input.seek(stopIndex);
}
}
}
hashCode() {
return this.cachedHashCode;
}
updateHashCode(hash) {
hash.update(this.cachedHashCode);
}
equals(other) {
if (this === other) {
return true;
} else if (!(other instanceof LexerActionExecutor)) {
return false;
} else if (this.cachedHashCode != other.cachedHashCode) {
return false;
} else if (this.lexerActions.length != other.lexerActions.length) {
return false;
} else {
const numActions = this.lexerActions.length
for (let idx = 0; idx < numActions; ++idx) {
if (!this.lexerActions[idx].equals(other.lexerActions[idx])) {
return false;
}
}
return true;
}
}
/**
* Creates a {@link LexerActionExecutor} which executes the actions for
* the input {@code lexerActionExecutor} followed by a specified
* {@code lexerAction}.
*
* @param lexerActionExecutor The executor for actions already traversed by
* the lexer while matching a token within a particular
* {@link LexerATNConfig}. If this is {@code null}, the method behaves as
* though it were an empty executor.
* @param lexerAction The lexer action to execute after the actions
* specified in {@code lexerActionExecutor}.
*
* @return {LexerActionExecutor} A {@link LexerActionExecutor} for executing the combine actions
* of {@code lexerActionExecutor} and {@code 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 executes the actions for
// the input {@code lexerActionExecutor} followed by a specified
// {@code lexerAction}.
//
// @param lexerActionExecutor The executor for actions already traversed by
// the lexer while matching a token within a particular
// {@link LexerATNConfig}. If this is {@code null}, the method behaves as
// though it were an empty executor.
// @param lexerAction The lexer action to execute after the actions
// specified in {@code lexerActionExecutor}.
//
// @return A {@link LexerActionExecutor} for executing the combine actions
// of {@code lexerActionExecutor} and {@code lexerAction}.
LexerActionExecutor.append = function(lexerActionExecutor, lexerAction) {
if (lexerActionExecutor === null) {
return new LexerActionExecutor([ lexerAction ]);
}
var lexerActions = lexerActionExecutor.lexerActions.concat([ lexerAction ]);
return new LexerActionExecutor(lexerActions);
};
// Creates a {@link LexerActionExecutor} which encodes the current offset module.exports = LexerActionExecutor;
// for position-dependent lexer actions.
//
// <p>Normally, when the executor encounters lexer actions where
// {@link LexerAction//isPositionDependent} returns {@code true}, it calls
// {@link IntStream//seek} on the input {@link CharStream} to set the input
// position to the <em>end</em> 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.</p>
//
// <p>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.</p>
//
// <p>If the current executor already has offsets assigned to all
// position-dependent lexer actions, the method returns {@code this}.</p>
//
// @param offset The current offset to assign to all position-dependent
// lexer actions which do not already have offsets assigned.
//
// @return A {@link LexerActionExecutor} which stores input stream offsets
// for all position-dependent lexer actions.
// /
LexerActionExecutor.prototype.fixOffsetBeforeMatch = function(offset) {
var updatedLexerActions = null;
for (var 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}.
//
// <p>This method calls {@link IntStream//seek} to set the position of the
// {@code 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.</p>
//
// @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
// {@code 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 {@code input} position to the beginning
// of the token.
// /
LexerActionExecutor.prototype.execute = function(lexer, input, startIndex) {
var requiresSeek = false;
var stopIndex = input.index;
try {
for (var i = 0; i < this.lexerActions.length; i++) {
var lexerAction = this.lexerActions[i];
if (lexerAction instanceof LexerIndexedCustomAction) {
var offset = lexerAction.offset;
input.seek(startIndex + offset);
lexerAction = lexerAction.action;
requiresSeek = (startIndex + offset) !== stopIndex;
} else if (lexerAction.isPositionDependent) {
input.seek(stopIndex);
requiresSeek = false;
}
lexerAction.execute(lexer);
}
} finally {
if (requiresSeek) {
input.seek(stopIndex);
}
}
};
LexerActionExecutor.prototype.hashCode = function() {
return this.cachedHashCode;
};
LexerActionExecutor.prototype.updateHashCode = function(hash) {
hash.update(this.cachedHashCode);
};
LexerActionExecutor.prototype.equals = function(other) {
if (this === other) {
return true;
} else if (!(other instanceof LexerActionExecutor)) {
return false;
} else if (this.cachedHashCode != other.cachedHashCode) {
return false;
} else if (this.lexerActions.length != other.lexerActions.length) {
return false;
} else {
var numActions = this.lexerActions.length
for (var idx = 0; idx < numActions; ++idx) {
if (!this.lexerActions[idx].equals(other.lexerActions[idx])) {
return false;
}
}
return true;
}
};
exports.LexerActionExecutor = LexerActionExecutor;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,404 +1,397 @@
//
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
//
// A tree structure used to record the semantic context in which const {Set, Hash} = require('./../Utils');
// an ATN configuration is valid. It's either a single predicate,
// a conjunction {@code p1&&p2}, or a sum of products {@code p1||p2}.
//
// <p>I have scoped the {@link AND}, {@link OR}, and {@link Predicate} subclasses of
// {@link SemanticContext} within the scope of this outer class.</p>
//
var Set = require('./../Utils').Set; /**
var Hash = require('./../Utils').Hash; * A tree structure used to record the semantic context in which
* an ATN configuration is valid. It's either a single predicate,
* a conjunction {@code p1&&p2}, or a sum of products {@code p1||p2}.
*
* <p>I have scoped the {@link AND}, {@link OR}, and {@link Predicate} subclasses of
* {@link SemanticContext} within the scope of this outer class.</p>
*/
class SemanticContext {
hashCode() {
const hash = new Hash();
this.updateHashCode(hash);
return hash.finish();
}
function SemanticContext() { /**
return this; * For context independent predicates, we evaluate them without a local
* context (i.e., null context). That way, we can evaluate them without
* having to create proper rule-specific context during prediction (as
* opposed to the parser, which creates them naturally). In a practical
* sense, this avoids a cast exception from RuleContext to myruleContext.
*
* <p>For context dependent predicates, we must pass in a local context so that
* references such as $arg evaluate properly as _localctx.arg. We only
* capture context dependent predicates in the context in which we begin
* prediction, so we passed in the outer context here in case of context
* dependent predicate evaluation.</p>
*/
evaluate(parser, outerContext) {}
/**
* Evaluate the precedence predicates for the context and reduce the result.
*
* @param parser The parser instance.
* @param outerContext The current parser context object.
* @return The simplified semantic context after precedence predicates are
* evaluated, which will be one of the following values.
* <ul>
* <li>{@link //NONE}: if the predicate simplifies to {@code true} after
* precedence predicates are evaluated.</li>
* <li>{@code null}: if the predicate simplifies to {@code false} after
* precedence predicates are evaluated.</li>
* <li>{@code this}: if the semantic context is not changed as a result of
* precedence predicate evaluation.</li>
* <li>A non-{@code null} {@link SemanticContext}: the new simplified
* semantic context after precedence predicates are evaluated.</li>
* </ul>
*/
evalPrecedence(parser, outerContext) {
return this;
}
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.opnds.length === 1) {
return result.opnds[0];
} else {
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.opnds.length === 1) {
return result.opnds[0];
} else {
return result;
}
}
} }
SemanticContext.prototype.hashCode = function() {
var hash = new Hash();
this.updateHashCode(hash);
return hash.finish();
};
// For context independent predicates, we evaluate them without a local class Predicate extends SemanticContext {
// context (i.e., null context). That way, we can evaluate them without constructor(ruleIndex, predIndex, isCtxDependent) {
// having to create proper rule-specific context during prediction (as super();
// opposed to the parser, which creates them naturally). In a practical this.ruleIndex = ruleIndex === undefined ? -1 : ruleIndex;
// sense, this avoids a cast exception from RuleContext to myruleContext. this.predIndex = predIndex === undefined ? -1 : predIndex;
// this.isCtxDependent = isCtxDependent === undefined ? false : isCtxDependent; // e.g., $i ref in pred
// <p>For context dependent predicates, we must pass in a local context so that }
// references such as $arg evaluate properly as _localctx.arg. We only
// capture context dependent predicates in the context in which we begin
// prediction, so we passed in the outer context here in case of context
// dependent predicate evaluation.</p>
//
SemanticContext.prototype.evaluate = function(parser, outerContext) {
};
// evaluate(parser, outerContext) {
// Evaluate the precedence predicates for the context and reduce the result. const localctx = this.isCtxDependent ? outerContext : null;
// return parser.sempred(localctx, this.ruleIndex, this.predIndex);
// @param parser The parser instance. }
// @param outerContext The current parser context object.
// @return The simplified semantic context after precedence predicates are
// evaluated, which will be one of the following values.
// <ul>
// <li>{@link //NONE}: if the predicate simplifies to {@code true} after
// precedence predicates are evaluated.</li>
// <li>{@code null}: if the predicate simplifies to {@code false} after
// precedence predicates are evaluated.</li>
// <li>{@code this}: if the semantic context is not changed as a result of
// precedence predicate evaluation.</li>
// <li>A non-{@code null} {@link SemanticContext}: the new simplified
// semantic context after precedence predicates are evaluated.</li>
// </ul>
//
SemanticContext.prototype.evalPrecedence = function(parser, outerContext) {
return this;
};
SemanticContext.andContext = function(a, b) { updateHashCode(hash) {
if (a === null || a === SemanticContext.NONE) { hash.update(this.ruleIndex, this.predIndex, this.isCtxDependent);
return b;
} }
if (b === null || b === SemanticContext.NONE) {
return a;
}
var result = new AND(a, b);
if (result.opnds.length === 1) {
return result.opnds[0];
} else {
return result;
}
};
SemanticContext.orContext = function(a, b) { equals(other) {
if (a === null) { if (this === other) {
return b; return true;
} else if (!(other instanceof Predicate)) {
return false;
} else {
return this.ruleIndex === other.ruleIndex &&
this.predIndex === other.predIndex &&
this.isCtxDependent === other.isCtxDependent;
}
} }
if (b === null) {
return a;
}
if (a === SemanticContext.NONE || b === SemanticContext.NONE) {
return SemanticContext.NONE;
}
var result = new OR(a, b);
if (result.opnds.length === 1) {
return result.opnds[0];
} else {
return result;
}
};
function Predicate(ruleIndex, predIndex, isCtxDependent) { toString() {
SemanticContext.call(this); return "{" + this.ruleIndex + ":" + this.predIndex + "}?";
this.ruleIndex = ruleIndex === undefined ? -1 : ruleIndex; }
this.predIndex = predIndex === undefined ? -1 : predIndex;
this.isCtxDependent = isCtxDependent === undefined ? false : isCtxDependent; // e.g., $i ref in pred
return this;
} }
Predicate.prototype = Object.create(SemanticContext.prototype); /**
Predicate.prototype.constructor = Predicate; * The default {@link SemanticContext}, which is semantically equivalent to
* a predicate of the form {@code {true}?}
//The default {@link SemanticContext}, which is semantically equivalent to */
//a predicate of the form {@code {true}?}.
//
SemanticContext.NONE = new Predicate(); SemanticContext.NONE = new Predicate();
Predicate.prototype.evaluate = function(parser, outerContext) { class PrecedencePredicate extends SemanticContext {
var localctx = this.isCtxDependent ? outerContext : null; constructor(precedence) {
return parser.sempred(localctx, this.ruleIndex, this.predIndex); super();
}; this.precedence = precedence === undefined ? 0 : precedence;
Predicate.prototype.updateHashCode = function(hash) {
hash.update(this.ruleIndex, this.predIndex, this.isCtxDependent);
};
Predicate.prototype.equals = function(other) {
if (this === other) {
return true;
} else if (!(other instanceof Predicate)) {
return false;
} else {
return this.ruleIndex === other.ruleIndex &&
this.predIndex === other.predIndex &&
this.isCtxDependent === other.isCtxDependent;
} }
};
Predicate.prototype.toString = function() { evaluate(parser, outerContext) {
return "{" + this.ruleIndex + ":" + this.predIndex + "}?"; return parser.precpred(outerContext, this.precedence);
};
function PrecedencePredicate(precedence) {
SemanticContext.call(this);
this.precedence = precedence === undefined ? 0 : precedence;
}
PrecedencePredicate.prototype = Object.create(SemanticContext.prototype);
PrecedencePredicate.prototype.constructor = PrecedencePredicate;
PrecedencePredicate.prototype.evaluate = function(parser, outerContext) {
return parser.precpred(outerContext, this.precedence);
};
PrecedencePredicate.prototype.evalPrecedence = function(parser, outerContext) {
if (parser.precpred(outerContext, this.precedence)) {
return SemanticContext.NONE;
} else {
return null;
} }
};
PrecedencePredicate.prototype.compareTo = function(other) { evalPrecedence(parser, outerContext) {
return this.precedence - other.precedence; if (parser.precpred(outerContext, this.precedence)) {
}; return SemanticContext.NONE;
} else {
PrecedencePredicate.prototype.updateHashCode = function(hash) { return null;
hash.update(31);
};
PrecedencePredicate.prototype.equals = function(other) {
if (this === other) {
return true;
} else if (!(other instanceof PrecedencePredicate)) {
return false;
} else {
return this.precedence === other.precedence;
}
};
PrecedencePredicate.prototype.toString = function() {
return "{"+this.precedence+">=prec}?";
};
PrecedencePredicate.filterPrecedencePredicates = function(set) {
var result = [];
set.values().map( function(context) {
if (context instanceof PrecedencePredicate) {
result.push(context);
} }
});
return result;
};
// A semantic context which is true whenever none of the contained contexts
// is false.
//
function AND(a, b) {
SemanticContext.call(this);
var operands = new Set();
if (a instanceof AND) {
a.opnds.map(function(o) {
operands.add(o);
});
} else {
operands.add(a);
} }
if (b instanceof AND) {
b.opnds.map(function(o) { compareTo(other) {
operands.add(o); return this.precedence - other.precedence;
});
} else {
operands.add(b);
} }
var precedencePredicates = PrecedencePredicate.filterPrecedencePredicates(operands);
if (precedencePredicates.length > 0) { updateHashCode(hash) {
// interested in the transition with the lowest precedence hash.update(31);
var reduced = null; }
precedencePredicates.map( function(p) {
if(reduced===null || p.precedence<reduced.precedence) { equals(other) {
reduced = p; if (this === other) {
return true;
} else if (!(other instanceof PrecedencePredicate)) {
return false;
} else {
return this.precedence === other.precedence;
}
}
toString() {
return "{"+this.precedence+">=prec}?";
}
static filterPrecedencePredicates(set) {
const result = [];
set.values().map( function(context) {
if (context instanceof PrecedencePredicate) {
result.push(context);
} }
}); });
operands.add(reduced); return result;
} }
this.opnds = operands.values();
return this;
} }
AND.prototype = Object.create(SemanticContext.prototype); class AND extends SemanticContext {
AND.prototype.constructor = AND; /**
* A semantic context which is true whenever none of the contained contexts
AND.prototype.equals = function(other) { * is false
if (this === other) { */
return true; constructor(a, b) {
} else if (!(other instanceof AND)) { super();
return false; const operands = new Set();
} else { if (a instanceof AND) {
return this.opnds === other.opnds; a.opnds.map(function(o) {
} operands.add(o);
}; });
} else {
AND.prototype.updateHashCode = function(hash) { operands.add(a);
hash.update(this.opnds, "AND");
};
//
// {@inheritDoc}
//
// <p>
// The evaluation of predicates by this context is short-circuiting, but
// unordered.</p>
//
AND.prototype.evaluate = function(parser, outerContext) {
for (var i = 0; i < this.opnds.length; i++) {
if (!this.opnds[i].evaluate(parser, outerContext)) {
return false;
} }
} if (b instanceof AND) {
return true; b.opnds.map(function(o) {
}; operands.add(o);
});
AND.prototype.evalPrecedence = function(parser, outerContext) { } else {
var differs = false; operands.add(b);
var operands = [];
for (var i = 0; i < this.opnds.length; i++) {
var context = this.opnds[i];
var evaluated = context.evalPrecedence(parser, outerContext);
differs |= (evaluated !== context);
if (evaluated === null) {
// The AND context is false if any element is false
return null;
} else if (evaluated !== SemanticContext.NONE) {
// Reduce the result by skipping true elements
operands.push(evaluated);
} }
} const precedencePredicates = PrecedencePredicate.filterPrecedencePredicates(operands);
if (!differs) { if (precedencePredicates.length > 0) {
return this; // interested in the transition with the lowest precedence
} let reduced = null;
if (operands.length === 0) { precedencePredicates.map( function(p) {
// all elements were true, so the AND context is true if(reduced===null || p.precedence<reduced.precedence) {
return SemanticContext.NONE; reduced = p;
} }
var result = null; });
operands.map(function(o) { operands.add(reduced);
result = result === null ? o : SemanticContext.andContext(result, o); }
}); this.opnds = operands.values();
return result;
};
AND.prototype.toString = function() {
var s = "";
this.opnds.map(function(o) {
s += "&& " + o.toString();
});
return s.length > 3 ? s.slice(3) : s;
};
//
// A semantic context which is true whenever at least one of the contained
// contexts is true.
//
function OR(a, b) {
SemanticContext.call(this);
var operands = new Set();
if (a instanceof OR) {
a.opnds.map(function(o) {
operands.add(o);
});
} else {
operands.add(a);
}
if (b instanceof OR) {
b.opnds.map(function(o) {
operands.add(o);
});
} else {
operands.add(b);
} }
var precedencePredicates = PrecedencePredicate.filterPrecedencePredicates(operands); equals(other) {
if (precedencePredicates.length > 0) { if (this === other) {
// interested in the transition with the highest precedence
var s = precedencePredicates.sort(function(a, b) {
return a.compareTo(b);
});
var reduced = s[s.length-1];
operands.add(reduced);
}
this.opnds = operands.values();
return this;
}
OR.prototype = Object.create(SemanticContext.prototype);
OR.prototype.constructor = OR;
OR.prototype.constructor = function(other) {
if (this === other) {
return true;
} else if (!(other instanceof OR)) {
return false;
} else {
return this.opnds === other.opnds;
}
};
OR.prototype.updateHashCode = function(hash) {
hash.update(this.opnds, "OR");
};
// <p>
// The evaluation of predicates by this context is short-circuiting, but
// unordered.</p>
//
OR.prototype.evaluate = function(parser, outerContext) {
for (var i = 0; i < this.opnds.length; i++) {
if (this.opnds[i].evaluate(parser, outerContext)) {
return true; return true;
} else if (!(other instanceof AND)) {
return false;
} else {
return this.opnds === other.opnds;
} }
} }
return false;
};
OR.prototype.evalPrecedence = function(parser, outerContext) { updateHashCode(hash) {
var differs = false; hash.update(this.opnds, "AND");
var operands = []; }
for (var i = 0; i < this.opnds.length; i++) {
var context = this.opnds[i]; /**
var evaluated = context.evalPrecedence(parser, outerContext); * {@inheritDoc}
differs |= (evaluated !== context); *
if (evaluated === SemanticContext.NONE) { * <p>
// The OR context is true if any element is true * The evaluation of predicates by this context is short-circuiting, but
* unordered.</p>
*/
evaluate(parser, outerContext) {
for (let i = 0; i < this.opnds.length; i++) {
if (!this.opnds[i].evaluate(parser, outerContext)) {
return false;
}
}
return true;
}
evalPrecedence(parser, outerContext) {
let differs = false;
const operands = [];
for (let i = 0; i < this.opnds.length; i++) {
const context = this.opnds[i];
const evaluated = context.evalPrecedence(parser, outerContext);
differs |= (evaluated !== context);
if (evaluated === null) {
// The AND context is false if any element is false
return null;
} else if (evaluated !== SemanticContext.NONE) {
// Reduce the result by skipping true elements
operands.push(evaluated);
}
}
if (!differs) {
return this;
}
if (operands.length === 0) {
// all elements were true, so the AND context is true
return SemanticContext.NONE; return SemanticContext.NONE;
} else if (evaluated !== null) { }
// Reduce the result by skipping false elements let result = null;
operands.push(evaluated); operands.map(function(o) {
result = result === null ? o : SemanticContext.andContext(result, o);
});
return result;
}
toString() {
let s = "";
this.opnds.map(function(o) {
s += "&& " + o.toString();
});
return s.length > 3 ? s.slice(3) : s;
}
}
class OR extends SemanticContext {
/**
* A semantic context which is true whenever at least one of the contained
* contexts is true
*/
constructor(a, b) {
super();
const operands = new Set();
if (a instanceof OR) {
a.opnds.map(function(o) {
operands.add(o);
});
} else {
operands.add(a);
}
if (b instanceof OR) {
b.opnds.map(function(o) {
operands.add(o);
});
} else {
operands.add(b);
}
const precedencePredicates = PrecedencePredicate.filterPrecedencePredicates(operands);
if (precedencePredicates.length > 0) {
// interested in the transition with the highest precedence
const s = precedencePredicates.sort(function(a, b) {
return a.compareTo(b);
});
const reduced = s[s.length-1];
operands.add(reduced);
}
this.opnds = operands.values();
}
equals(other) {
if (this === other) {
return true;
} else if (!(other instanceof OR)) {
return false;
} else {
return this.opnds === other.opnds;
} }
} }
if (!differs) {
return this;
}
if (operands.length === 0) {
// all elements were false, so the OR context is false
return null;
}
var result = null;
operands.map(function(o) {
return result === null ? o : SemanticContext.orContext(result, o);
});
return result;
};
OR.prototype.toString = function() { updateHashCode(hash) {
var s = ""; hash.update(this.opnds, "OR");
this.opnds.map(function(o) { }
s += "|| " + o.toString();
});
return s.length > 3 ? s.slice(3) : s;
};
exports.SemanticContext = SemanticContext; /**
exports.PrecedencePredicate = PrecedencePredicate; * <p>
exports.Predicate = Predicate; * The evaluation of predicates by this context is short-circuiting, but
* unordered.</p>
*/
evaluate(parser, outerContext) {
for (let i = 0; i < this.opnds.length; i++) {
if (this.opnds[i].evaluate(parser, outerContext)) {
return true;
}
}
return false;
}
evalPrecedence(parser, outerContext) {
let differs = false;
const operands = [];
for (let i = 0; i < this.opnds.length; i++) {
const context = this.opnds[i];
const evaluated = context.evalPrecedence(parser, outerContext);
differs |= (evaluated !== context);
if (evaluated === SemanticContext.NONE) {
// The OR context is true if any element is true
return SemanticContext.NONE;
} else if (evaluated !== null) {
// Reduce the result by skipping false elements
operands.push(evaluated);
}
}
if (!differs) {
return this;
}
if (operands.length === 0) {
// all elements were false, so the OR context is false
return null;
}
const result = null;
operands.map(function(o) {
return result === null ? o : SemanticContext.orContext(result, o);
});
return result;
}
toString() {
let s = "";
this.opnds.map(function(o) {
s += "|| " + o.toString();
});
return s.length > 3 ? s.slice(3) : s;
}
}
module.exports = {
SemanticContext,
PrecedencePredicate,
Predicate
}

View File

@ -2,45 +2,48 @@
* Use of this file is governed by the BSD 3-clause license that * 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. * can be found in the LICENSE.txt file in the project root.
*/ */
//
// An ATN transition between any two ATN states. Subclasses define const {Token} = require('./../Token');
// atom, set, epsilon, action, predicate, rule transitions. const {IntervalSet} = require('./../IntervalSet');
// const {Predicate, PrecedencePredicate} = require('./SemanticContext');
// <p>This is a one way link. It emanates from a state (usually via a list of
// transitions) and has a target state.</p>
//
// <p>Since we never have to change the ATN transitions once we construct it,
// we can fix these transitions as specific classes. The DFA transitions
// on the other hand need to update the labels as it adds transitions to
// the states. We'll use the term Edge for the DFA to distinguish them from
// ATN transitions.</p>
var Token = require('./../Token').Token; /**
var Interval = require('./../IntervalSet').Interval; * An ATN transition between any two ATN states. Subclasses define
var IntervalSet = require('./../IntervalSet').IntervalSet; * atom, set, epsilon, action, predicate, rule transitions.
var Predicate = require('./SemanticContext').Predicate; *
var PrecedencePredicate = require('./SemanticContext').PrecedencePredicate; * <p>This is a one way link. It emanates from a state (usually via a list of
* transitions) and has a target state.</p>
function Transition (target) { *
// The target of this transition. * <p>Since we never have to change the ATN transitions once we construct it,
if (target===undefined || target===null) { * we can fix these transitions as specific classes. The DFA transitions
throw "target cannot be null."; * on the other hand need to update the labels as it adds transitions to
* the states. We'll use the term Edge for the DFA to distinguish them from
* ATN transitions.</p>
*/
class Transition {
constructor(target) {
// The target of this transition.
if (target===undefined || target===null) {
throw "target cannot be null.";
}
this.target = target;
// Are we epsilon, action, sempred?
this.isEpsilon = false;
this.label = null;
} }
this.target = target;
// Are we epsilon, action, sempred?
this.isEpsilon = false;
this.label = null;
return this;
} }
// constants for serialization
// constants for serialization
Transition.EPSILON = 1; Transition.EPSILON = 1;
Transition.RANGE = 2; Transition.RANGE = 2;
Transition.RULE = 3; Transition.RULE = 3;
Transition.PREDICATE = 4; // e.g., {isType(input.LT(1))}? // e.g., {isType(input.LT(1))}?
Transition.PREDICATE = 4;
Transition.ATOM = 5; Transition.ATOM = 5;
Transition.ACTION = 6; Transition.ACTION = 6;
Transition.SET = 7; // ~(A|B) or ~atom, wildcard, which convert to next 2 // ~(A|B) or ~atom, wildcard, which convert to next 2
Transition.SET = 7;
Transition.NOT_SET = 8; Transition.NOT_SET = 8;
Transition.WILDCARD = 9; Transition.WILDCARD = 9;
Transition.PRECEDENCE = 10; Transition.PRECEDENCE = 10;
@ -74,243 +77,227 @@ Transition.serializationTypes = {
// TODO: make all transitions sets? no, should remove set edges // TODO: make all transitions sets? no, should remove set edges
function AtomTransition(target, label) {
Transition.call(this, target); class AtomTransition extends Transition {
this.label_ = label; // The token type or character value; or, signifies special label. constructor(target, label) {
this.label = this.makeLabel(); super(target);
this.serializationType = Transition.ATOM; // The token type or character value; or, signifies special label.
return this; this.label_ = label;
this.label = this.makeLabel();
this.serializationType = Transition.ATOM;
}
makeLabel() {
const s = new IntervalSet();
s.addOne(this.label_);
return s;
}
matches(symbol, minVocabSymbol, maxVocabSymbol) {
return this.label_ === symbol;
}
toString() {
return this.label_;
}
} }
AtomTransition.prototype = Object.create(Transition.prototype);
AtomTransition.prototype.constructor = AtomTransition;
AtomTransition.prototype.makeLabel = function() { class RuleTransition extends Transition {
var s = new IntervalSet(); constructor(ruleStart, ruleIndex, precedence, followState) {
s.addOne(this.label_); super(ruleStart);
return s; // ptr to the rule definition object for this rule ref
}; this.ruleIndex = ruleIndex;
this.precedence = precedence;
// what node to begin computations following ref to rule
this.followState = followState;
this.serializationType = Transition.RULE;
this.isEpsilon = true;
}
AtomTransition.prototype.matches = function( symbol, minVocabSymbol, maxVocabSymbol) { matches(symbol, minVocabSymbol, maxVocabSymbol) {
return this.label_ === symbol; return false;
}; }
AtomTransition.prototype.toString = function() {
return this.label_;
};
function RuleTransition(ruleStart, ruleIndex, precedence, followState) {
Transition.call(this, ruleStart);
this.ruleIndex = ruleIndex; // ptr to the rule definition object for this rule ref
this.precedence = precedence;
this.followState = followState; // what node to begin computations following ref to rule
this.serializationType = Transition.RULE;
this.isEpsilon = true;
return this;
} }
RuleTransition.prototype = Object.create(Transition.prototype); class EpsilonTransition extends Transition {
RuleTransition.prototype.constructor = RuleTransition; constructor(target, outermostPrecedenceReturn) {
super(target);
this.serializationType = Transition.EPSILON;
this.isEpsilon = true;
this.outermostPrecedenceReturn = outermostPrecedenceReturn;
}
RuleTransition.prototype.matches = function(symbol, minVocabSymbol, maxVocabSymbol) { matches(symbol, minVocabSymbol, maxVocabSymbol) {
return false; return false;
}; }
toString() {
function EpsilonTransition(target, outermostPrecedenceReturn) { return "epsilon";
Transition.call(this, target); }
this.serializationType = Transition.EPSILON;
this.isEpsilon = true;
this.outermostPrecedenceReturn = outermostPrecedenceReturn;
return this;
} }
EpsilonTransition.prototype = Object.create(Transition.prototype);
EpsilonTransition.prototype.constructor = EpsilonTransition;
EpsilonTransition.prototype.matches = function( symbol, minVocabSymbol, maxVocabSymbol) { class RangeTransition extends Transition {
return false; constructor(target, start, stop) {
}; super(target);
this.serializationType = Transition.RANGE;
this.start = start;
this.stop = stop;
this.label = this.makeLabel();
}
EpsilonTransition.prototype.toString = function() { makeLabel() {
return "epsilon"; const s = new IntervalSet();
}; s.addRange(this.start, this.stop);
return s;
}
function RangeTransition(target, start, stop) { matches(symbol, minVocabSymbol, maxVocabSymbol) {
Transition.call(this, target); return symbol >= this.start && symbol <= this.stop;
this.serializationType = Transition.RANGE; }
this.start = start;
this.stop = stop; toString() {
this.label = this.makeLabel(); return "'" + String.fromCharCode(this.start) + "'..'" + String.fromCharCode(this.stop) + "'";
return this; }
} }
RangeTransition.prototype = Object.create(Transition.prototype);
RangeTransition.prototype.constructor = RangeTransition;
RangeTransition.prototype.makeLabel = function() { class AbstractPredicateTransition extends Transition {
var s = new IntervalSet(); constructor(target) {
s.addRange(this.start, this.stop); super(target);
return s; }
};
RangeTransition.prototype.matches = function(symbol, minVocabSymbol, maxVocabSymbol) {
return symbol >= this.start && symbol <= this.stop;
};
RangeTransition.prototype.toString = function() {
return "'" + String.fromCharCode(this.start) + "'..'" + String.fromCharCode(this.stop) + "'";
};
function AbstractPredicateTransition(target) {
Transition.call(this, target);
return this;
} }
AbstractPredicateTransition.prototype = Object.create(Transition.prototype); class PredicateTransition extends AbstractPredicateTransition {
AbstractPredicateTransition.prototype.constructor = AbstractPredicateTransition; constructor(target, ruleIndex, predIndex, isCtxDependent) {
super(target);
this.serializationType = Transition.PREDICATE;
this.ruleIndex = ruleIndex;
this.predIndex = predIndex;
this.isCtxDependent = isCtxDependent; // e.g., $i ref in pred
this.isEpsilon = true;
}
function PredicateTransition(target, ruleIndex, predIndex, isCtxDependent) { matches(symbol, minVocabSymbol, maxVocabSymbol) {
AbstractPredicateTransition.call(this, target); return false;
this.serializationType = Transition.PREDICATE; }
this.ruleIndex = ruleIndex;
this.predIndex = predIndex; getPredicate() {
this.isCtxDependent = isCtxDependent; // e.g., $i ref in pred return new Predicate(this.ruleIndex, this.predIndex, this.isCtxDependent);
this.isEpsilon = true; }
return this;
toString() {
return "pred_" + this.ruleIndex + ":" + this.predIndex;
}
} }
PredicateTransition.prototype = Object.create(AbstractPredicateTransition.prototype);
PredicateTransition.prototype.constructor = PredicateTransition;
PredicateTransition.prototype.matches = function(symbol, minVocabSymbol, maxVocabSymbol) { class ActionTransition extends Transition {
return false; constructor(target, ruleIndex, actionIndex, isCtxDependent) {
}; super(target);
this.serializationType = Transition.ACTION;
this.ruleIndex = ruleIndex;
this.actionIndex = actionIndex===undefined ? -1 : actionIndex;
this.isCtxDependent = isCtxDependent===undefined ? false : isCtxDependent; // e.g., $i ref in pred
this.isEpsilon = true;
}
PredicateTransition.prototype.getPredicate = function() { matches(symbol, minVocabSymbol, maxVocabSymbol) {
return new Predicate(this.ruleIndex, this.predIndex, this.isCtxDependent); return false;
}; }
PredicateTransition.prototype.toString = function() { toString() {
return "pred_" + this.ruleIndex + ":" + this.predIndex; return "action_" + this.ruleIndex + ":" + this.actionIndex;
}; }
function ActionTransition(target, ruleIndex, actionIndex, isCtxDependent) {
Transition.call(this, target);
this.serializationType = Transition.ACTION;
this.ruleIndex = ruleIndex;
this.actionIndex = actionIndex===undefined ? -1 : actionIndex;
this.isCtxDependent = isCtxDependent===undefined ? false : isCtxDependent; // e.g., $i ref in pred
this.isEpsilon = true;
return this;
} }
ActionTransition.prototype = Object.create(Transition.prototype);
ActionTransition.prototype.constructor = ActionTransition;
ActionTransition.prototype.matches = function(symbol, minVocabSymbol, maxVocabSymbol) {
return false;
};
ActionTransition.prototype.toString = function() {
return "action_" + this.ruleIndex + ":" + this.actionIndex;
};
// A transition containing a set of values. // A transition containing a set of values.
function SetTransition(target, set) { class SetTransition extends Transition {
Transition.call(this, target); constructor(target, set) {
this.serializationType = Transition.SET; super(target);
if (set !==undefined && set !==null) { this.serializationType = Transition.SET;
this.label = set; if (set !==undefined && set !==null) {
} else { this.label = set;
this.label = new IntervalSet(); } else {
this.label.addOne(Token.INVALID_TYPE); this.label = new IntervalSet();
this.label.addOne(Token.INVALID_TYPE);
}
}
matches(symbol, minVocabSymbol, maxVocabSymbol) {
return this.label.contains(symbol);
}
toString() {
return this.label.toString();
} }
return this;
} }
SetTransition.prototype = Object.create(Transition.prototype); class NotSetTransition extends SetTransition {
SetTransition.prototype.constructor = SetTransition; constructor(target, set) {
super(target, set);
this.serializationType = Transition.NOT_SET;
}
SetTransition.prototype.matches = function(symbol, minVocabSymbol, maxVocabSymbol) { matches(symbol, minVocabSymbol, maxVocabSymbol) {
return this.label.contains(symbol); return symbol >= minVocabSymbol && symbol <= maxVocabSymbol &&
}; !super.matches(symbol, minVocabSymbol, maxVocabSymbol);
}
toString() {
SetTransition.prototype.toString = function() { return '~' + super.toString();
return this.label.toString(); }
};
function NotSetTransition(target, set) {
SetTransition.call(this, target, set);
this.serializationType = Transition.NOT_SET;
return this;
} }
NotSetTransition.prototype = Object.create(SetTransition.prototype); class WildcardTransition extends Transition {
NotSetTransition.prototype.constructor = NotSetTransition; constructor(target) {
super(target);
this.serializationType = Transition.WILDCARD;
}
NotSetTransition.prototype.matches = function(symbol, minVocabSymbol, maxVocabSymbol) { matches(symbol, minVocabSymbol, maxVocabSymbol) {
return symbol >= minVocabSymbol && symbol <= maxVocabSymbol && return symbol >= minVocabSymbol && symbol <= maxVocabSymbol;
!SetTransition.prototype.matches.call(this, symbol, minVocabSymbol, maxVocabSymbol); }
};
NotSetTransition.prototype.toString = function() { toString() {
return '~' + SetTransition.prototype.toString.call(this); return ".";
}; }
function WildcardTransition(target) {
Transition.call(this, target);
this.serializationType = Transition.WILDCARD;
return this;
} }
WildcardTransition.prototype = Object.create(Transition.prototype); class PrecedencePredicateTransition extends AbstractPredicateTransition {
WildcardTransition.prototype.constructor = WildcardTransition; constructor(target, precedence) {
super(target);
this.serializationType = Transition.PRECEDENCE;
this.precedence = precedence;
this.isEpsilon = true;
}
matches(symbol, minVocabSymbol, maxVocabSymbol) {
return false;
}
WildcardTransition.prototype.matches = function(symbol, minVocabSymbol, maxVocabSymbol) { getPredicate() {
return symbol >= minVocabSymbol && symbol <= maxVocabSymbol; return new PrecedencePredicate(this.precedence);
}; }
WildcardTransition.prototype.toString = function() { toString() {
return "."; return this.precedence + " >= _p";
}; }
function PrecedencePredicateTransition(target, precedence) {
AbstractPredicateTransition.call(this, target);
this.serializationType = Transition.PRECEDENCE;
this.precedence = precedence;
this.isEpsilon = true;
return this;
} }
PrecedencePredicateTransition.prototype = Object.create(AbstractPredicateTransition.prototype); module.exports = {
PrecedencePredicateTransition.prototype.constructor = PrecedencePredicateTransition; Transition,
AtomTransition,
PrecedencePredicateTransition.prototype.matches = function(symbol, minVocabSymbol, maxVocabSymbol) { SetTransition,
return false; NotSetTransition,
}; RuleTransition,
ActionTransition,
PrecedencePredicateTransition.prototype.getPredicate = function() { EpsilonTransition,
return new PrecedencePredicate(this.precedence); RangeTransition,
}; WildcardTransition,
PredicateTransition,
PrecedencePredicateTransition.prototype.toString = function() { PrecedencePredicateTransition,
return this.precedence + " >= _p"; AbstractPredicateTransition
}; }
exports.Transition = Transition;
exports.AtomTransition = AtomTransition;
exports.SetTransition = SetTransition;
exports.NotSetTransition = NotSetTransition;
exports.RuleTransition = RuleTransition;
exports.ActionTransition = ActionTransition;
exports.EpsilonTransition = EpsilonTransition;
exports.RangeTransition = RangeTransition;
exports.WildcardTransition = WildcardTransition;
exports.PredicateTransition = PredicateTransition;
exports.PrecedencePredicateTransition = PrecedencePredicateTransition;
exports.AbstractPredicateTransition = AbstractPredicateTransition;

View File

@ -4,7 +4,7 @@
*/ */
exports.ATN = require('./ATN'); exports.ATN = require('./ATN');
exports.ATNDeserializer = require('./ATNDeserializer').ATNDeserializer; exports.ATNDeserializer = require('./ATNDeserializer');
exports.LexerATNSimulator = require('./LexerATNSimulator').LexerATNSimulator; exports.LexerATNSimulator = require('./LexerATNSimulator');
exports.ParserATNSimulator = require('./ParserATNSimulator').ParserATNSimulator; exports.ParserATNSimulator = require('./ParserATNSimulator');
exports.PredictionMode = require('./PredictionMode').PredictionMode; exports.PredictionMode = require('./PredictionMode');