10
10
* @param {string|class } token to emit
11
11
*/
12
12
export function State ( token ) {
13
+ // this.n = null; // DEBUG: State name
13
14
this . j = { } ; // IMPLEMENTATION 1
14
15
// this.j = []; // IMPLEMENTATION 2
15
16
this . jr = [ ] ;
@@ -49,11 +50,21 @@ State.prototype = {
49
50
* transitioned to on the given input regardless of what that input
50
51
* previously did.
51
52
*
52
- * @param {string } input character or token to transition on
53
+ * @param {string } input character or token type to transition on
53
54
* @param {Token|State } tokenOrState transition to a matching state
54
55
* @returns State taken after the given input
55
56
*/
56
57
tt ( input , tokenOrState ) {
58
+ if ( input instanceof Array ) {
59
+ // Recursive case
60
+ if ( input . length === 0 ) { return ; }
61
+ const nextState = this . tt ( input [ 0 ] , tokenOrState ) ;
62
+ for ( let i = 1 ; i < input . length ; i ++ ) {
63
+ this . tt ( input [ i ] , nextState ) ;
64
+ }
65
+ return nextState ;
66
+ }
67
+
57
68
if ( tokenOrState && tokenOrState . j ) {
58
69
// State, default a basic transition
59
70
this . j [ input ] = tokenOrState ;
@@ -92,13 +103,21 @@ State.prototype = {
92
103
* Utility function to create state without using new keyword (reduced file size
93
104
* when minified)
94
105
*/
95
- export const makeState = ( ) => new State ( ) ;
106
+ export const makeState = ( /*name*/ ) => {
107
+ const s = new State ( ) ;
108
+ // if (name) { s.n = name; } // DEBUG
109
+ return s ;
110
+ } ;
96
111
97
112
/**
98
113
* Similar to previous except it is an accepting state that emits a token
99
114
* @param {Token } token
100
115
*/
101
- export const makeAcceptingState = ( token ) => new State ( token ) ;
116
+ export const makeAcceptingState = ( token /*, name*/ ) => {
117
+ const s = new State ( token ) ;
118
+ // if (name) { s.n = name; } // DEBUG
119
+ return s ;
120
+ } ;
102
121
103
122
/**
104
123
* Create a transition from startState to nextState via the given character
@@ -112,6 +131,7 @@ export const makeT = (startState, input, nextState) => {
112
131
113
132
// IMPLEMENTATION 2: Add to array (slower)
114
133
// startState.j.push([input, nextState]);
134
+ return startState . j [ input ] ;
115
135
} ;
116
136
117
137
/**
@@ -127,7 +147,7 @@ export const makeRegexT = (startState, regex, nextState) => {
127
147
/**
128
148
* Follow the transition from the given character to the next state
129
149
* @param {State } state
130
- * @param {Token } input character or other concrete token type to transition
150
+ * @param {string| Token } input character or other concrete token type to transition
131
151
* @returns {?State } the next state, if any
132
152
*/
133
153
export const takeT = ( state , input ) => {
@@ -145,8 +165,8 @@ export const takeT = (state, input) => {
145
165
146
166
for ( let i = 0 ; i < state . jr . length ; i ++ ) {
147
167
const regex = state . jr [ i ] [ 0 ] ;
148
- const nextState = state . jr [ i ] [ 1 ] ;
149
- if ( regex . test ( input ) ) { return nextState ; }
168
+ const nextState = state . jr [ i ] [ 1 ] ; // note: might be empty to prevent default jump
169
+ if ( nextState && regex . test ( input ) ) { return nextState ; }
150
170
}
151
171
// Nowhere left to jump! Return default, if any
152
172
return state . jd ;
@@ -176,6 +196,7 @@ export const makeBatchT = (startState, transitions) => {
176
196
for ( let i = 0 ; i < transitions . length ; i ++ ) {
177
197
const input = transitions [ i ] [ 0 ] ;
178
198
const nextState = transitions [ i ] [ 1 ] ;
199
+ // if (!nextState.n && typeof input === 'string') { nextState.n = input; } // DEBUG
179
200
makeT ( startState , input , nextState ) ;
180
201
}
181
202
} ;
@@ -193,6 +214,7 @@ export const makeBatchT = (startState, transitions) => {
193
214
* @param {string } str
194
215
* @param {Token } endStateFactory
195
216
* @param {Token } defaultStateFactory
217
+ * @return {State } the final state
196
218
*/
197
219
export const makeChainT = ( state , str , endState , defaultStateFactory ) => {
198
220
let i = 0 , len = str . length , nextState ;
@@ -203,7 +225,7 @@ export const makeChainT = (state, str, endState, defaultStateFactory) => {
203
225
i ++ ;
204
226
}
205
227
206
- if ( i >= len ) { return [ ] ; } // no new tokens were added
228
+ if ( i >= len ) { return state ; } // no new tokens were added
207
229
208
230
while ( i < len - 1 ) {
209
231
nextState = defaultStateFactory ( ) ;
@@ -213,4 +235,6 @@ export const makeChainT = (state, str, endState, defaultStateFactory) => {
213
235
}
214
236
215
237
makeT ( state , str [ len - 1 ] , endState ) ;
238
+ // if (!endState.n) { endState.n === str; } // DEBUG
239
+ return endState ;
216
240
} ;
0 commit comments