blob: fb6999614e92fb2505d36de8bce6efae0413130e [file] [log] [blame]
/** A DFA implemented as a set of transition tables.
*
* Any state that has a semantic predicate edge is special; those states
* are generated with if-then-else structures in a specialStateTransition()
* which is generated by cyclicDFA template.
*
* There are at most 32767 states (16-bit signed short).
* Could get away with byte sometimes but would have to generate different
* types and the simulation code too. For a point of reference, the Java
* lexer's Tokens rule DFA has 326 states roughly.
*/
org.antlr.runtime.DFA = function() {};
org.antlr.runtime.DFA.prototype = {
/** From the input stream, predict what alternative will succeed
* using this DFA (representing the covering regular approximation
* to the underlying CFL). Return an alternative number 1..n. Throw
* an exception upon error.
*/
predict: function(input) {
var mark = input.mark(), // remember where decision started in input
s = 0, // we always start at s0
specialState,
c,
snext;
try {
while ( true ) {
specialState = this.special[s];
if ( specialState>=0 ) {
s = this.specialStateTransition(specialState,input);
if (s===-1) {
this.noViableAlt(s, input);
return 0;
}
input.consume();
continue;
}
if ( this.accept[s] >= 1 ) {
return this.accept[s];
}
// look for a normal char transition
c = input.LA(1); // -1 == \uFFFF, all tokens fit in 65000 space
if (c===org.antlr.runtime.Token.EOF) {
c = -1;
} else if (org.antlr.lang.isString(c)) {
c = c.charCodeAt(0);
}
if (c>=this.min[s] && c<=this.max[s]) {
snext = this.transition[s][c-this.min[s]]; // move to next state
if ( snext < 0 ) {
// was in range but not a normal transition
// must check EOT, which is like the else clause.
// eot[s]>=0 indicates that an EOT edge goes to another
// state.
if ( this.eot[s]>=0 ) { // EOT Transition to accept state?
s = this.eot[s];
input.consume();
// TODO: I had this as return accept[eot[s]]
// which assumed here that the EOT edge always
// went to an accept...faster to do this, but
// what about predicated edges coming from EOT
// target?
continue;
}
this.noViableAlt(s,input);
return 0;
}
s = snext;
input.consume();
continue;
}
if ( this.eot[s]>=0 ) { // EOT Transition?
s = this.eot[s];
input.consume();
continue;
}
if ( c==org.antlr.runtime.Token.EOF && this.eof[s]>=0 ) { // EOF Transition to accept state?
return this.accept[this.eof[s]];
}
// not in range and not EOF/EOT, must be invalid symbol
this.noViableAlt(s,input);
return 0;
}
}
finally {
input.rewind(mark);
}
},
noViableAlt: function(s, input) {
if (this.recognizer.state.backtracking>0) {
this.recognizer.state.failed=true;
return;
}
var nvae =
new org.antlr.runtime.NoViableAltException(this.getDescription(),
this.decisionNumber,
s,
input);
this.error(nvae);
throw nvae;
},
/** A hook for debugging interface */
error: function(nvae) { },
specialStateTransition: function(s, input) {
return -1;
},
getDescription: function() {
return "n/a";
}
};
org.antlr.lang.augmentObject(org.antlr.runtime.DFA, {
/** Given a String that has a run-length-encoding of some unsigned shorts
* like "\1\2\3\9", convert to short[] {2,9,9,9}.
*/
unpackEncodedString: function(encodedString) {
// walk first to find how big it is.
var i,
data = [],
di = 0,
n,
v,
j;
for (i=0; i<encodedString.length; i+=2) {
n = encodedString.charCodeAt(i);
v = encodedString.charCodeAt(i+1);
if (v===0xffff) {
v = -1; // overflow at 16 bits
}
// add v n times to data
for (j=1; j<=n; j++) {
data[di++] = v;
}
}
return data;
},
// alias
unpackEncodedStringToUnsignedChars: function(encodedString) {
return org.antlr.runtime.DFA.unpackEncodedString(encodedString);
}
});