Skip to content

Commit 5f56f69

Browse files
authored
improvement(message-compiler): Change to generate AST with linked message error (#245)
1 parent ac96927 commit 5f56f69

File tree

3 files changed

+659
-52
lines changed

3 files changed

+659
-52
lines changed

packages/message-compiler/src/parser.ts

Lines changed: 74 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Position, createLocation, SourceLocation } from './location'
22
import { ParserOptions } from './options'
33
import { createCompileError, CompileErrorCodes } from './errors'
4-
import { Tokenizer, createTokenizer, TokenTypes } from './tokenizer'
4+
import { Tokenizer, createTokenizer, TokenTypes, Token } from './tokenizer'
55

66
export const enum NodeTypes {
77
Resource, // 0
@@ -213,9 +213,36 @@ export function createParser(options: ParserOptions = {}): Parser {
213213
return node
214214
}
215215

216-
function parseLinkedModifier(tokenizer: Tokenizer): LinkedModifierNode {
216+
function parseLinkedModifier(
217+
tokenizer: Tokenizer
218+
): {
219+
nextConsumeToken?: Token
220+
node: LinkedModifierNode
221+
} {
217222
const token = tokenizer.nextToken()
218223
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+
}
219246
// check token
220247
if (token.value == null) {
221248
emitError(
@@ -226,15 +253,11 @@ export function createParser(options: ParserOptions = {}): Parser {
226253
token.type
227254
)
228255
}
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
235256
node.value = token.value || ''
236257
endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition())
237-
return node
258+
return {
259+
node
260+
}
238261
}
239262

240263
function parseLinkedKey(tokenizer: Tokenizer, value: string): LinkedKeyNode {
@@ -249,7 +272,12 @@ export function createParser(options: ParserOptions = {}): Parser {
249272
return node
250273
}
251274

252-
function parseLinked(tokenizer: Tokenizer): LinkedNode {
275+
function parseLinked(
276+
tokenizer: Tokenizer
277+
): {
278+
nextConsumeToken?: Token
279+
node: LinkedNode
280+
} {
253281
const context = tokenizer.context()
254282
const linkedNode = startNode(
255283
NodeTypes.Linked,
@@ -259,8 +287,9 @@ export function createParser(options: ParserOptions = {}): Parser {
259287

260288
let token = tokenizer.nextToken()
261289
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()
264293
}
265294

266295
// asset check token
@@ -329,10 +358,36 @@ export function createParser(options: ParserOptions = {}): Parser {
329358
}
330359
linkedNode.key = parseLiteral(tokenizer, token.value || '')
331360
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
332385
}
333386

334387
endNode(linkedNode, tokenizer.currentOffset(), tokenizer.currentPosition())
335-
return linkedNode
388+
return {
389+
node: linkedNode
390+
}
336391
}
337392

338393
function parseMessage(tokenizer: Tokenizer): MessageNode {
@@ -352,8 +407,10 @@ export function createParser(options: ParserOptions = {}): Parser {
352407
) as MessageNode
353408
node.items = []
354409

410+
let nextToken: Token | null = null
355411
do {
356-
const token = tokenizer.nextToken()
412+
const token = nextToken || tokenizer.nextToken()
413+
nextToken = null
357414
switch (token.type) {
358415
case TokenTypes.Text:
359416
if (token.value == null) {
@@ -404,7 +461,9 @@ export function createParser(options: ParserOptions = {}): Parser {
404461
node.items.push(parseLiteral(tokenizer, token.value || ''))
405462
break
406463
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
408467
break
409468
}
410469
} while (

0 commit comments

Comments
 (0)