diff --git a/runtime/JavaScript/src/antlr4/atn/ATN.js b/runtime/JavaScript/src/antlr4/atn/ATN.js index b08131d40..78570513b 100644 --- a/runtime/JavaScript/src/antlr4/atn/ATN.js +++ b/runtime/JavaScript/src/antlr4/atn/ATN.js @@ -6,91 +6,117 @@ var LL1Analyzer = require('./../LL1Analyzer').LL1Analyzer; var IntervalSet = require('./../IntervalSet').IntervalSet; -function ATN(grammarType , maxTokenType) { +class ATN { + constructor(grammarType , maxTokenType) { - // Used for runtime deserialization of ATNs from strings/// - // The type of the ATN. - this.grammarType = grammarType; - // The maximum value for any symbol recognized by a transition in the ATN. - this.maxTokenType = maxTokenType; - this.states = []; - // Each subrule/rule is a decision point and we must track them so we - // can go back later and build DFA predictors for them. This includes - // all the rules, subrules, optional blocks, ()+, ()* etc... - this.decisionToState = []; - // Maps from rule index to starting state number. - this.ruleToStartState = []; - // Maps from rule index to stop state number. - this.ruleToStopState = null; - this.modeNameToStartState = {}; - // For lexer ATNs, this maps the rule index to the resulting token type. - // For parser ATNs, this maps the rule index to the generated bypass token - // type if the - // {@link ATNDeserializationOptions//isGenerateRuleBypassTransitions} - // deserialization option was specified; otherwise, this is {@code null}. - 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; -} + // Used for runtime deserialization of ATNs from strings/// + // The type of the ATN. + this.grammarType = grammarType; + // The maximum value for any symbol recognized by a transition in the ATN. + this.maxTokenType = maxTokenType; + this.states = []; + // Each subrule/rule is a decision point and we must track them so we + // can go back later and build DFA predictors for them. This includes + // all the rules, subrules, optional blocks, ()+, ()* etc... + this.decisionToState = []; + // Maps from rule index to starting state number. + this.ruleToStartState = []; + // Maps from rule index to stop state number. + this.ruleToStopState = null; + this.modeNameToStartState = {}; + // For lexer ATNs, this maps the rule index to the resulting token type. + // For parser ATNs, this maps the rule index to the generated bypass token + // type if the + // {@link ATNDeserializationOptions//isGenerateRuleBypassTransitions} + // deserialization option was specified; otherwise, this is {@code null}. + 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 = []; + } // 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. -ATN.prototype.nextTokensInContext = function(s, ctx) { - var anal = new LL1Analyzer(this); - return anal.LOOK(s, null, ctx); -}; + nextTokensInContext(s, ctx) { + var anal = new LL1Analyzer(this); + return anal.LOOK(s, null, ctx); + } // Compute the set of valid tokens that can occur starting in {@code s} and // staying in same rule. {@link Token//EPSILON} is in set if we reach end of // rule. -ATN.prototype.nextTokensNoContext = function(s) { - if (s.nextTokenWithinRule !== null ) { + nextTokensNoContext(s) { + if (s.nextTokenWithinRule !== null ) { + return s.nextTokenWithinRule; + } + s.nextTokenWithinRule = this.nextTokensInContext(s, null); + s.nextTokenWithinRule.readOnly = true; return s.nextTokenWithinRule; } - s.nextTokenWithinRule = this.nextTokensInContext(s, null); - s.nextTokenWithinRule.readOnly = true; - return s.nextTokenWithinRule; -}; -ATN.prototype.nextTokens = function(s, ctx) { - if ( ctx===undefined ) { - return this.nextTokensNoContext(s); - } else { - return this.nextTokensInContext(s, ctx); + nextTokens(s, ctx) { + if ( ctx===undefined ) { + return this.nextTokensNoContext(s); + } else { + return this.nextTokensInContext(s, ctx); + } } -}; -ATN.prototype.addState = function( state) { - if ( state !== null ) { - state.atn = this; - state.stateNumber = this.states.length; + addState(state) { + if ( state !== null ) { + state.atn = this; + state.stateNumber = this.states.length; + } + this.states.push(state); } - this.states.push(state); -}; -ATN.prototype.removeState = function( state) { - 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]; + removeState(state) { + this.states[state.stateNumber] = null; // just free mem, don't shift states in list } -}; + + defineDecisionState(s) { + this.decisionToState.push(s); + s.decision = this.decisionToState.length-1; + return s.decision; + } + + getDecisionState(decision) { + if (this.decisionToState.length===0) { + return null; + } else { + return this.decisionToState[decision]; + } + } + + getExpectedTokens(stateNumber, ctx ) { + if ( stateNumber < 0 || stateNumber >= this.states.length ) { + throw("Invalid state number."); + } + var s = this.states[stateNumber]; + var following = this.nextTokens(s); + if (!following.contains(Token.EPSILON)) { + return following; + } + var expected = new IntervalSet(); + expected.addSet(following); + expected.removeOne(Token.EPSILON); + while (ctx !== null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) { + var invokingState = this.states[ctx.invokingState]; + var 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; + } +} // Computes the set of input symbols which could follow ATN state number // {@code stateNumber} in the specified full {@code context}. This method @@ -111,32 +137,6 @@ ATN.prototype.getDecisionState = function( decision) { // number {@code stateNumber} var Token = require('./../Token').Token; -ATN.prototype.getExpectedTokens = function( stateNumber, ctx ) { - if ( stateNumber < 0 || stateNumber >= this.states.length ) { - throw("Invalid state number."); - } - var s = this.states[stateNumber]; - var following = this.nextTokens(s); - if (!following.contains(Token.EPSILON)) { - return following; - } - var expected = new IntervalSet(); - expected.addSet(following); - expected.removeOne(Token.EPSILON); - while (ctx !== null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) { - var invokingState = this.states[ctx.invokingState]; - var 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; -}; - ATN.INVALID_ALT_NUMBER = 0; module.exports = ATN;