forked from jasder/antlr
refactored ATNState.js to es 6 classes
use module.exports use jsdoc
This commit is contained in:
parent
430b7c1917
commit
78afe57b7d
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue