refactored ATNState.js to es 6 classes

use module.exports
use jsdoc
This commit is contained in:
Camilo Roca 2020-03-06 19:12:09 +01:00
parent 430b7c1917
commit 78afe57b7d
1 changed files with 244 additions and 255 deletions

View File

@ -1,84 +1,115 @@
//
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
//
// 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"/>
//
const INITIAL_NUM_TRANSITIONS = 4;
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() {
// 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;
return this;
toString() {
return this.stateNumber;
}
equals(other) {
if (other instanceof ATNState) {
return this.stateNumber===other.stateNumber;
} else {
return false;
}
}
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
@ -113,214 +144,172 @@ ATNState.serializationNames = [
ATNState.INVALID_STATE_NUMBER = -1;
ATNState.prototype.toString = function() {
return this.stateNumber;
};
ATNState.prototype.equals = function(other) {
if (other instanceof ATNState) {
return this.stateNumber===other.stateNumber;
} else {
return false;
class BasicState extends ATNState {
constructor() {
super();
this.stateType = ATNState.BASIC;
}
};
}
ATNState.prototype.isNonGreedyExitState = function() {
return false;
};
ATNState.prototype.addTransition = function(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;
class DecisionState extends ATNState {
constructor() {
super();
this.decision = -1;
this.nonGreedy = false;
return this;
}
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);
BasicState.prototype.constructor = BasicState;
function DecisionState() {
ATNState.call(this);
this.decision = -1;
this.nonGreedy = false;
return this;
class BasicBlockStartState extends BlockStartState {
constructor() {
super();
this.stateType = ATNState.BLOCK_START;
return this;
}
}
DecisionState.prototype = Object.create(ATNState.prototype);
DecisionState.prototype.constructor = DecisionState;
// The start of a regular {@code (...)} block.
function BlockStartState() {
DecisionState.call(this);
this.endState = null;
return this;
/**
* Terminal node of a simple {@code (a|b|c)} block
*/
class BlockEndState extends ATNState {
constructor() {
super();
this.stateType = ATNState.BLOCK_END;
this.startState = null;
return this;
}
}
BlockStartState.prototype = Object.create(DecisionState.prototype);
BlockStartState.prototype.constructor = BlockStartState;
function BasicBlockStartState() {
BlockStartState.call(this);
this.stateType = ATNState.BLOCK_START;
return this;
/**
* 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
* error handling
*/
class RuleStopState extends ATNState {
constructor() {
super();
this.stateType = ATNState.RULE_STOP;
return this;
}
}
BasicBlockStartState.prototype = Object.create(BlockStartState.prototype);
BasicBlockStartState.prototype.constructor = BasicBlockStartState;
// Terminal node of a simple {@code (a|b|c)} block.
function BlockEndState() {
ATNState.call(this);
this.stateType = ATNState.BLOCK_END;
this.startState = null;
return this;
class RuleStartState extends ATNState {
constructor() {
super();
this.stateType = ATNState.RULE_START;
this.stopState = null;
this.isPrecedenceRule = false;
return this;
}
}
BlockEndState.prototype = Object.create(ATNState.prototype);
BlockEndState.prototype.constructor = BlockEndState;
// 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
// error handling.
//
function RuleStopState() {
ATNState.call(this);
this.stateType = ATNState.RULE_STOP;
return this;
/**
* 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.
*/
class PlusLoopbackState extends DecisionState {
constructor() {
super();
this.stateType = ATNState.PLUS_LOOP_BACK;
return this;
}
}
RuleStopState.prototype = Object.create(ATNState.prototype);
RuleStopState.prototype.constructor = RuleStopState;
function RuleStartState() {
ATNState.call(this);
this.stateType = ATNState.RULE_START;
this.stopState = null;
this.isPrecedenceRule = false;
return this;
/**
* 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
* it for completeness. In reality, the {@link PlusLoopbackState} node is the
* real decision-making note for {@code A+}
*/
class PlusBlockStartState extends BlockStartState {
constructor() {
super();
this.stateType = ATNState.PLUS_BLOCK_START;
this.loopBackState = null;
return this;
}
}
RuleStartState.prototype = Object.create(ATNState.prototype);
RuleStartState.prototype.constructor = RuleStartState;
// 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.
//
function PlusLoopbackState() {
DecisionState.call(this);
this.stateType = ATNState.PLUS_LOOP_BACK;
return this;
/**
* The block that begins a closure loop
*/
class StarBlockStartState extends BlockStartState {
constructor() {
super();
this.stateType = ATNState.STAR_BLOCK_START;
return this;
}
}
PlusLoopbackState.prototype = Object.create(DecisionState.prototype);
PlusLoopbackState.prototype.constructor = PlusLoopbackState;
// 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
// 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;
class StarLoopbackState extends ATNState {
constructor() {
super();
this.stateType = ATNState.STAR_LOOP_BACK;
return this;
}
}
PlusBlockStartState.prototype = Object.create(BlockStartState.prototype);
PlusBlockStartState.prototype.constructor = PlusBlockStartState;
// The block that begins a closure loop.
function StarBlockStartState() {
BlockStartState.call(this);
this.stateType = ATNState.STAR_BLOCK_START;
return this;
class StarLoopEntryState extends DecisionState {
constructor() {
super();
this.stateType = ATNState.STAR_LOOP_ENTRY;
this.loopBackState = null;
// Indicates whether this state can benefit from a precedence DFA during SLL decision making.
this.isPrecedenceDecision = null;
return this;
}
}
StarBlockStartState.prototype = Object.create(BlockStartState.prototype);
StarBlockStartState.prototype.constructor = StarBlockStartState;
function StarLoopbackState() {
ATNState.call(this);
this.stateType = ATNState.STAR_LOOP_BACK;
return this;
/**
* Mark the end of a * or + loop
*/
class LoopEndState extends ATNState {
constructor() {
super();
this.stateType = ATNState.LOOP_END;
this.loopBackState = null;
return this;
}
}
StarLoopbackState.prototype = Object.create(ATNState.prototype);
StarLoopbackState.prototype.constructor = StarLoopbackState;
function StarLoopEntryState() {
DecisionState.call(this);
this.stateType = ATNState.STAR_LOOP_ENTRY;
this.loopBackState = null;
// Indicates whether this state can benefit from a precedence DFA during SLL decision making.
this.isPrecedenceDecision = null;
return this;
/**
* The Tokens rule start state linking to each lexer rule start state
*/
class TokensStartState extends DecisionState {
constructor() {
super();
this.stateType = ATNState.TOKEN_START;
return this;
}
}
StarLoopEntryState.prototype = Object.create(DecisionState.prototype);
StarLoopEntryState.prototype.constructor = StarLoopEntryState;
// Mark the end of a * or + loop.
function LoopEndState() {
ATNState.call(this);
this.stateType = ATNState.LOOP_END;
this.loopBackState = null;
return this;
module.exports = {
ATNState,
BasicState,
DecisionState,
BlockStartState,
BlockEndState,
LoopEndState,
RuleStartState,
RuleStopState,
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;