@@ -129,9 +129,13 @@ export class TokenizerState {
129129 startingIndex : number
130130
131131 /**
132- * Type and position of the last delimiter.
132+ * Type of the last delimiter.
133133 */
134- lastDelimiter : [ string , number ]
134+ lastDelimiter : string | undefined
135+ /**
136+ * Position of the last delimiter.
137+ */
138+ lastDelimiterIndex : number
135139
136140 librarySchema : string
137141
@@ -148,7 +152,8 @@ export class TokenizerState {
148152 this . currentToken = ''
149153 this . groupDepth = 0
150154 this . startingIndex = 0
151- this . lastDelimiter = [ undefined , - 1 ]
155+ this . lastDelimiter = undefined
156+ this . lastDelimiterIndex = - 1
152157 this . librarySchema = ''
153158 this . lastSlash = - 1
154159 this . currentGroupStack = [ [ ] ]
@@ -174,7 +179,7 @@ export class HedStringTokenizer {
174179 * The current state of the tokenizer.
175180 * @internal
176181 */
177- private state : TokenizerState
182+ private state : TokenizerState | null
178183
179184 /**
180185 * Constructor.
@@ -233,25 +238,25 @@ export class HedStringTokenizer {
233238 * @internal
234239 */
235240 finalizeTokenizer ( ) : void {
236- if ( this . state . lastDelimiter [ 0 ] === CHARACTERS . OPENING_COLUMN ) {
241+ if ( this . state . lastDelimiter === CHARACTERS . OPENING_COLUMN ) {
237242 // Extra opening brace
238243 this . pushIssue (
239244 'unclosedCurlyBrace' ,
240- this . state . lastDelimiter [ 1 ] ,
245+ this . state . lastDelimiterIndex ,
241246 'The string ends before the previous "{" has been closed.' ,
242247 ) // Extra opening brace
243- } else if ( this . state . lastDelimiter [ 0 ] === CHARACTERS . OPENING_GROUP ) {
248+ } else if ( this . state . lastDelimiter === CHARACTERS . OPENING_GROUP ) {
244249 // Extra opening parenthesis
245250 this . pushIssue (
246251 'unclosedParentheses' ,
247- this . state . lastDelimiter [ 1 ] ,
252+ this . state . lastDelimiterIndex ,
248253 'The string ends before the previous "(" has been closed.' ,
249254 ) // Extra opening parenthesis
250255 } else if (
251- this . state . lastDelimiter [ 0 ] === CHARACTERS . COMMA &&
252- this . hedString . slice ( this . state . lastDelimiter [ 1 ] + 1 ) . trim ( ) . length === 0
256+ this . state . lastDelimiter === CHARACTERS . COMMA &&
257+ this . hedString . slice ( this . state . lastDelimiterIndex + 1 ) . trim ( ) . length === 0
253258 ) {
254- this . pushIssue ( 'emptyTagFound' , this . state . lastDelimiter [ 1 ] , 'Probably extra commas at end.' ) // Extra comma
259+ this . pushIssue ( 'emptyTagFound' , this . state . lastDelimiterIndex , 'Probably extra commas at end.' ) // Extra comma
255260 } else if ( this . state . lastSlash >= 0 && this . hedString . slice ( this . state . lastSlash + 1 ) . trim ( ) . length === 0 ) {
256261 this . pushIssue (
257262 'extraSlash' ,
@@ -261,12 +266,12 @@ export class HedStringTokenizer {
261266 }
262267 if (
263268 this . state . currentToken . trim ( ) . length > 0 &&
264- ! [ undefined , CHARACTERS . COMMA ] . includes ( this . state . lastDelimiter [ 0 ] )
269+ ! [ undefined , CHARACTERS . COMMA ] . includes ( this . state . lastDelimiter )
265270 ) {
266271 // Missing comma
267272 this . pushIssue (
268273 'commaMissing' ,
269- this . state . lastDelimiter [ 1 ] + 1 ,
274+ this . state . lastDelimiterIndex + 1 ,
270275 `This likely occurred near the end of "${ this . hedString } ".` ,
271276 )
272277 } else {
@@ -322,25 +327,25 @@ export class HedStringTokenizer {
322327 * @internal
323328 */
324329 handleComma ( i : number ) : void {
325- const trimmed = this . hedString . slice ( this . state . lastDelimiter [ 1 ] + 1 , i ) . trim ( )
330+ const trimmed = this . hedString . slice ( this . state . lastDelimiterIndex + 1 , i ) . trim ( )
326331 if (
327- [ CHARACTERS . OPENING_GROUP , CHARACTERS . COMMA , undefined ] . includes ( this . state . lastDelimiter [ 0 ] ) &&
332+ [ CHARACTERS . OPENING_GROUP , CHARACTERS . COMMA , undefined ] . includes ( this . state . lastDelimiter ) &&
328333 trimmed . length === 0
329334 ) {
330335 this . pushIssue (
331336 'emptyTagFound' ,
332337 i ,
333338 'Usually a comma after another comma or an open parenthesis or at beginning of string.' ,
334339 )
335- } else if ( this . state . lastDelimiter [ 0 ] === CHARACTERS . OPENING_COLUMN ) {
340+ } else if ( this . state . lastDelimiter === CHARACTERS . OPENING_COLUMN ) {
336341 this . pushIssue (
337342 'unclosedCurlyBrace' ,
338- this . state . lastDelimiter [ 1 ] ,
343+ this . state . lastDelimiterIndex ,
339344 'A "{" appears before the previous "{" was closed.' ,
340345 ) // Unclosed curly brace Ex: "{ x,"
341346 }
342347 if (
343- [ CHARACTERS . CLOSING_GROUP , CHARACTERS . CLOSING_COLUMN ] . includes ( this . state . lastDelimiter [ 0 ] ) &&
348+ [ CHARACTERS . CLOSING_GROUP , CHARACTERS . CLOSING_COLUMN ] . includes ( this . state . lastDelimiter ) &&
344349 trimmed . length > 0
345350 ) {
346351 // A tag followed a group or column with no comma Ex: (x) yz
@@ -350,7 +355,8 @@ export class HedStringTokenizer {
350355 } else {
351356 this . resetToken ( i ) // After a group or column
352357 }
353- this . state . lastDelimiter = [ CHARACTERS . COMMA , i ]
358+ this . state . lastDelimiter = CHARACTERS . COMMA
359+ this . state . lastDelimiterIndex = i
354360 }
355361
356362 /**
@@ -384,24 +390,25 @@ export class HedStringTokenizer {
384390 * @internal
385391 */
386392 handleOpeningGroup ( i : number ) : void {
387- if ( this . state . lastDelimiter [ 0 ] === CHARACTERS . OPENING_COLUMN ) {
393+ if ( this . state . lastDelimiter === CHARACTERS . OPENING_COLUMN ) {
388394 this . pushIssue (
389395 'unclosedCurlyBrace' ,
390- this . state . lastDelimiter [ 1 ] ,
396+ this . state . lastDelimiterIndex ,
391397 'Previous "{" is not closed and braces or parentheses cannot appear inside braces.' ,
392398 ) // After open curly brace Ex: "{ ("
393- } else if ( this . state . lastDelimiter [ 0 ] === CHARACTERS . CLOSING_COLUMN ) {
394- this . pushIssue ( 'commaMissing' , this . state . lastDelimiter [ 1 ] , 'Missing comma after "}".' ) // After close curly brace Ex: " } ("
395- } else if ( this . state . lastDelimiter [ 0 ] === CHARACTERS . CLOSING_GROUP ) {
396- this . pushIssue ( 'commaMissing' , this . state . lastDelimiter [ 1 ] + 1 , 'Missing comma after ")".' ) // After close group Ex: ") ("
399+ } else if ( this . state . lastDelimiter === CHARACTERS . CLOSING_COLUMN ) {
400+ this . pushIssue ( 'commaMissing' , this . state . lastDelimiterIndex , 'Missing comma after "}".' ) // After close curly brace Ex: " } ("
401+ } else if ( this . state . lastDelimiter === CHARACTERS . CLOSING_GROUP ) {
402+ this . pushIssue ( 'commaMissing' , this . state . lastDelimiterIndex + 1 , 'Missing comma after ")".' ) // After close group Ex: ") ("
397403 } else if ( this . state . currentToken . trim ( ) . length > 0 ) {
398404 this . pushInvalidTag ( 'commaMissing' , i , this . state . currentToken . trim ( ) , 'Missing comma before "(".' ) // After tag Ex: "x ("
399405 } else {
400406 this . state . currentGroupStack . push ( [ ] )
401407 this . state . parenthesesStack . push ( new GroupSpec ( i , undefined , [ ] ) )
402408 this . resetToken ( i )
403409 this . state . groupDepth ++
404- this . state . lastDelimiter = [ CHARACTERS . OPENING_GROUP , i ]
410+ this . state . lastDelimiter = CHARACTERS . OPENING_GROUP
411+ this . state . lastDelimiterIndex = i
405412 }
406413 }
407414
@@ -414,19 +421,20 @@ export class HedStringTokenizer {
414421 handleClosingGroup ( i : number ) : void {
415422 if ( this . state . groupDepth <= 0 ) {
416423 this . pushIssue ( 'unopenedParenthesis' , i , 'A ")" appears before a matching "(".' )
417- } else if ( this . state . lastDelimiter [ 0 ] === CHARACTERS . OPENING_COLUMN ) {
424+ } else if ( this . state . lastDelimiter === CHARACTERS . OPENING_COLUMN ) {
418425 this . pushIssue (
419426 'unclosedCurlyBrace' ,
420- this . state . lastDelimiter [ 1 ] ,
427+ this . state . lastDelimiterIndex ,
421428 'A "{" appears before the previous "{" has been closed.' ,
422429 ) // After open curly brace Ex: "{ )"
423430 } else {
424- if ( [ CHARACTERS . OPENING_GROUP , CHARACTERS . COMMA ] . includes ( this . state . lastDelimiter [ 0 ] ) ) {
431+ if ( [ CHARACTERS . OPENING_GROUP , CHARACTERS . COMMA ] . includes ( this . state . lastDelimiter ) ) {
425432 // Should be a tag here
426433 this . pushTag ( i )
427434 }
428435 this . closeGroup ( i ) // Close the group by updating its bounds and moving it to the parent group.
429- this . state . lastDelimiter = [ CHARACTERS . CLOSING_GROUP , i ]
436+ this . state . lastDelimiter = CHARACTERS . CLOSING_GROUP
437+ this . state . lastDelimiterIndex = i
430438 }
431439 }
432440
@@ -439,10 +447,11 @@ export class HedStringTokenizer {
439447 handleOpeningColumn ( i : number ) : void {
440448 if ( this . state . currentToken . trim ( ) . length > 0 ) {
441449 this . pushInvalidCharacterIssue ( CHARACTERS . OPENING_COLUMN , i , 'Brace in the middle of a tag Ex: "x {".' )
442- } else if ( this . state . lastDelimiter [ 0 ] === CHARACTERS . OPENING_COLUMN ) {
450+ } else if ( this . state . lastDelimiter === CHARACTERS . OPENING_COLUMN ) {
443451 this . pushIssue ( 'nestedCurlyBrace' , i , 'Often after another open brace Ex: Ex: "{x{".' )
444452 } else {
445- this . state . lastDelimiter = [ CHARACTERS . OPENING_COLUMN , i ]
453+ this . state . lastDelimiter = CHARACTERS . OPENING_COLUMN
454+ this . state . lastDelimiterIndex = i
446455 }
447456 }
448457
@@ -453,17 +462,18 @@ export class HedStringTokenizer {
453462 * @internal
454463 */
455464 handleClosingColumn ( i : number ) : void {
456- if ( this . state . lastDelimiter [ 0 ] !== CHARACTERS . OPENING_COLUMN ) {
465+ if ( this . state . lastDelimiter !== CHARACTERS . OPENING_COLUMN ) {
457466 this . pushIssue ( 'unopenedCurlyBrace' , i , 'No matching open brace Ex: " x}".' )
458467 } else if ( ! this . state . currentToken . trim ( ) ) {
459468 this . pushIssue ( 'emptyCurlyBrace' , i , 'Column slice cannot be empty Ex: "{ }".' )
460469 } else {
461470 // Close column by updating bounds and moving it to the parent group, push a column splice on the stack.
462471 this . state . currentGroupStack [ this . state . groupDepth ] . push (
463- new ColumnSpliceSpec ( this . state . currentToken . trim ( ) , this . state . lastDelimiter [ 1 ] , i ) ,
472+ new ColumnSpliceSpec ( this . state . currentToken . trim ( ) , this . state . lastDelimiterIndex , i ) ,
464473 )
465474 this . resetToken ( i )
466- this . state . lastDelimiter = [ CHARACTERS . CLOSING_COLUMN , i ]
475+ this . state . lastDelimiter = CHARACTERS . CLOSING_COLUMN
476+ this . state . lastDelimiterIndex = i
467477 }
468478 }
469479
0 commit comments