Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javascript: migrate prototypical ATN objects to ES6 #2771

Merged
merged 22 commits into from Mar 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e7b935e
refactored ATN to be an es6 class
carocad Mar 6, 2020
15720d1
use jsdoc and const/let
carocad Mar 6, 2020
8f1b2e5
use jsdoc and const/let
carocad Mar 6, 2020
1b440d3
use jsdoc and const/let
carocad Mar 6, 2020
2246528
use module.exports
carocad Mar 6, 2020
7324e09
refactored ATNConfigSet.js to use es 6 classes
carocad Mar 6, 2020
430b7c1
refactored ATNDeserializationOptions.js to es 6 classes
carocad Mar 6, 2020
78afe57
refactored ATNState.js to es 6 classes
carocad Mar 6, 2020
44331c0
refactored ATNType.js to be a simple object with static definitions
carocad Mar 6, 2020
d61e4d5
refactored LexerAction.js to use es 6 classes
carocad Mar 6, 2020
4f8527e
refactored ATNDeserializer.js to use es6 classes
carocad Mar 6, 2020
43f896d
use const/let for better variable scoping
carocad Mar 6, 2020
01c5dca
refactored ATNSimulator.js to use es6 classes
carocad Mar 6, 2020
9aeac6d
refactored LexerActionExecutor.js to use es6 classes
carocad Mar 6, 2020
d1dce9e
refactored LexerATNSimulator.js to use es6 classes
carocad Mar 6, 2020
7f271a1
refactored ParserATNSimulator.js to use es6 classes
carocad Mar 6, 2020
21538eb
refactored PredictionMode.js to use es6 classes
carocad Mar 7, 2020
6ebe0d1
refactored SemanticContext.js.js to use es6 classes
carocad Mar 7, 2020
6a38ae5
fix: no need for return on constructor
carocad Mar 7, 2020
ae8602a
refactored Transition.js to use es6 classes
carocad Mar 7, 2020
51bcf5f
refactored import statements to use object destructuring and avoid re…
carocad Mar 7, 2020
2988f32
fix: invalid object destructuring
carocad Mar 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions runtime/JavaScript/src/antlr4/Parser.js
Expand Up @@ -7,8 +7,8 @@ var Token = require('./Token').Token;
var ParseTreeListener = require('./tree/Tree').ParseTreeListener;
var Recognizer = require('./Recognizer').Recognizer;
var DefaultErrorStrategy = require('./error/ErrorStrategy').DefaultErrorStrategy;
var ATNDeserializer = require('./atn/ATNDeserializer').ATNDeserializer;
var ATNDeserializationOptions = require('./atn/ATNDeserializationOptions').ATNDeserializationOptions;
var ATNDeserializer = require('./atn/ATNDeserializer');
var ATNDeserializationOptions = require('./atn/ATNDeserializationOptions');
var TerminalNode = require('./tree/Tree').TerminalNode;
var ErrorNode = require('./tree/Tree').ErrorNode;

Expand Down Expand Up @@ -671,4 +671,4 @@ Parser.prototype.setTrace = function(trace) {
}
};

exports.Parser = Parser;
exports.Parser = Parser;
244 changes: 129 additions & 115 deletions runtime/JavaScript/src/antlr4/atn/ATN.js
Expand Up @@ -3,139 +3,153 @@
* can be found in the LICENSE.txt file in the project root.
*/

var LL1Analyzer = require('./../LL1Analyzer').LL1Analyzer;
var IntervalSet = require('./../IntervalSet').IntervalSet;
const {LL1Analyzer} = require('./../LL1Analyzer');
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.
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);
};
/**
* 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 {@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 ) {
/**
* 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
*/
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
}
};

// Computes the set of input symbols which could follow ATN state number
// {@code stateNumber} in the specified full {@code context}. This method
// considers the complete parser context, but does not evaluate semantic
// predicates (i.e. all predicates encountered during the calculation are
// assumed true). If a path in the ATN exists from the starting state to the
// {@link RuleStopState} of the outermost context without matching any
// symbols, {@link Token//EOF} is added to the returned set.
//
// <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 ) {
if ( stateNumber < 0 || stateNumber >= this.states.length ) {
throw("Invalid state number.");
defineDecisionState(s) {
this.decisionToState.push(s);
s.decision = this.decisionToState.length-1;
return s.decision;
}
var s = this.states[stateNumber];
var following = this.nextTokens(s);
if (!following.contains(Token.EPSILON)) {
return following;

getDecisionState(decision) {
if (this.decisionToState.length===0) {
return null;
} else {
return this.decisionToState[decision];
}
}
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);

/**
* Computes the set of input symbols which could follow ATN state number
* {@code stateNumber} in the specified full {@code context}. This method
* considers the complete parser context, but does not evaluate semantic
* predicates (i.e. all predicates encountered during the calculation are
* assumed true). If a path in the ATN exists from the starting state to the
* {@link RuleStopState} of the outermost context without matching any
* symbols, {@link Token//EOF} is added to the returned set.
*
* <p>If {@code context} is {@code null}, it is treated as
* {@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.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;

Expand Down