1
1
import { Position , createLocation , SourceLocation } from './location'
2
2
import { ParserOptions } from './options'
3
3
import { createCompileError , CompileErrorCodes } from './errors'
4
- import { Tokenizer , createTokenizer , TokenTypes } from './tokenizer'
4
+ import { Tokenizer , createTokenizer , TokenTypes , Token } from './tokenizer'
5
5
6
6
export const enum NodeTypes {
7
7
Resource , // 0
@@ -213,9 +213,36 @@ export function createParser(options: ParserOptions = {}): Parser {
213
213
return node
214
214
}
215
215
216
- function parseLinkedModifier ( tokenizer : Tokenizer ) : LinkedModifierNode {
216
+ function parseLinkedModifier (
217
+ tokenizer : Tokenizer
218
+ ) : {
219
+ nextConsumeToken ?: Token
220
+ node : LinkedModifierNode
221
+ } {
217
222
const token = tokenizer . nextToken ( )
218
223
const context = tokenizer . context ( )
224
+ const { lastOffset : offset , lastStartLoc : loc } = context // get linked dot loc
225
+ const node = startNode (
226
+ NodeTypes . LinkedModifier ,
227
+ offset ,
228
+ loc
229
+ ) as LinkedModifierNode
230
+ if ( token . type !== TokenTypes . LinkedModifier ) {
231
+ // empty modifier
232
+ emitError (
233
+ tokenizer ,
234
+ CompileErrorCodes . UNEXPECTED_LEXICAL_ANALYSIS ,
235
+ context . lastStartLoc ,
236
+ 0 ,
237
+ token . type
238
+ )
239
+ node . value = ''
240
+ endNode ( node , offset , loc )
241
+ return {
242
+ nextConsumeToken : token ,
243
+ node
244
+ }
245
+ }
219
246
// check token
220
247
if ( token . value == null ) {
221
248
emitError (
@@ -226,15 +253,11 @@ export function createParser(options: ParserOptions = {}): Parser {
226
253
token . type
227
254
)
228
255
}
229
- const { lastOffset : offset , lastStartLoc : loc } = context // get linked dot loc
230
- const node = startNode (
231
- NodeTypes . LinkedModifier ,
232
- offset ,
233
- loc
234
- ) as LinkedModifierNode
235
256
node . value = token . value || ''
236
257
endNode ( node , tokenizer . currentOffset ( ) , tokenizer . currentPosition ( ) )
237
- return node
258
+ return {
259
+ node
260
+ }
238
261
}
239
262
240
263
function parseLinkedKey ( tokenizer : Tokenizer , value : string ) : LinkedKeyNode {
@@ -249,7 +272,12 @@ export function createParser(options: ParserOptions = {}): Parser {
249
272
return node
250
273
}
251
274
252
- function parseLinked ( tokenizer : Tokenizer ) : LinkedNode {
275
+ function parseLinked (
276
+ tokenizer : Tokenizer
277
+ ) : {
278
+ nextConsumeToken ?: Token
279
+ node : LinkedNode
280
+ } {
253
281
const context = tokenizer . context ( )
254
282
const linkedNode = startNode (
255
283
NodeTypes . Linked ,
@@ -259,8 +287,9 @@ export function createParser(options: ParserOptions = {}): Parser {
259
287
260
288
let token = tokenizer . nextToken ( )
261
289
if ( token . type === TokenTypes . LinkedDot ) {
262
- linkedNode . modifier = parseLinkedModifier ( tokenizer )
263
- token = tokenizer . nextToken ( )
290
+ const parsed = parseLinkedModifier ( tokenizer )
291
+ linkedNode . modifier = parsed . node
292
+ token = parsed . nextConsumeToken || tokenizer . nextToken ( )
264
293
}
265
294
266
295
// asset check token
@@ -329,10 +358,36 @@ export function createParser(options: ParserOptions = {}): Parser {
329
358
}
330
359
linkedNode . key = parseLiteral ( tokenizer , token . value || '' )
331
360
break
361
+ default :
362
+ // empty key
363
+ emitError (
364
+ tokenizer ,
365
+ CompileErrorCodes . UNEXPECTED_LEXICAL_ANALYSIS ,
366
+ context . lastStartLoc ,
367
+ 0 ,
368
+ token . type
369
+ )
370
+ const nextContext = tokenizer . context ( )
371
+ const emptyLinkedKeyNode = startNode (
372
+ NodeTypes . LinkedKey ,
373
+ nextContext . offset ,
374
+ nextContext . startLoc
375
+ ) as LinkedKeyNode
376
+ emptyLinkedKeyNode . value = ''
377
+ endNode ( emptyLinkedKeyNode , nextContext . offset , nextContext . startLoc )
378
+ linkedNode . key = emptyLinkedKeyNode
379
+ endNode ( linkedNode , nextContext . offset , nextContext . startLoc )
380
+ return {
381
+ nextConsumeToken : token ,
382
+ node : linkedNode
383
+ }
384
+ break
332
385
}
333
386
334
387
endNode ( linkedNode , tokenizer . currentOffset ( ) , tokenizer . currentPosition ( ) )
335
- return linkedNode
388
+ return {
389
+ node : linkedNode
390
+ }
336
391
}
337
392
338
393
function parseMessage ( tokenizer : Tokenizer ) : MessageNode {
@@ -352,8 +407,10 @@ export function createParser(options: ParserOptions = {}): Parser {
352
407
) as MessageNode
353
408
node . items = [ ]
354
409
410
+ let nextToken : Token | null = null
355
411
do {
356
- const token = tokenizer . nextToken ( )
412
+ const token = nextToken || tokenizer . nextToken ( )
413
+ nextToken = null
357
414
switch ( token . type ) {
358
415
case TokenTypes . Text :
359
416
if ( token . value == null ) {
@@ -404,7 +461,9 @@ export function createParser(options: ParserOptions = {}): Parser {
404
461
node . items . push ( parseLiteral ( tokenizer , token . value || '' ) )
405
462
break
406
463
case TokenTypes . LinkedAlias :
407
- node . items . push ( parseLinked ( tokenizer ) )
464
+ const parsed = parseLinked ( tokenizer )
465
+ node . items . push ( parsed . node )
466
+ nextToken = parsed . nextConsumeToken || null
408
467
break
409
468
}
410
469
} while (
0 commit comments