Skip to content

Commit

Permalink
Lexer: erroneous token kinds; unterminated literals
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Jun 11, 2023
1 parent c02de72 commit 1658fa4
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface SyntaxError {
}

export const prettyLexerError = (token: ParseToken): string => {
return red(`lexer error: unknown token \`${token.value}\``)
return red(`lexer error: ${token.kind} token \`${token.value}\``)
}

export const prettySyntaxError = (error: SyntaxError): string => {
Expand Down
8 changes: 4 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { tokenize } from './lexer/lexer'
import { erroneousTokenKinds, tokenize } from './lexer/lexer'
import { existsSync, readFileSync } from 'fs'
import { join, resolve } from 'path'
import { compactNode, Parser } from './parser/parser'
Expand Down Expand Up @@ -26,9 +26,9 @@ if (!existsSync(sourcePath)) {
const source = { str: readFileSync(sourcePath).toString(), filename: path }

const tokens = tokenize(source.str)
const unknownTokens = tokens.filter(t => t.kind === 'unknown')
if (unknownTokens.length > 0) {
for (const t of unknownTokens) {
const errorTokens = tokens.filter(t => erroneousTokenKinds.includes(t.kind))
if (errorTokens.length > 0) {
for (const t of errorTokens) {
console.error(prettySourceMessage(prettyLexerError(t), t.location.start, source))
}
process.exit(1)
Expand Down
6 changes: 3 additions & 3 deletions src/lexer/lexer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ let main = (): Unit {
})

it('tokenize string literal', () => {
expect(tokenize(`"string 123 \n ok"`)).toEqual([
{ kind: 'string', value: `"string 123 \n ok"`, location: { start: 0, end: 16 } },
{ kind: 'eof', value: '', location: { start: 17, end: 17 } }
expect(tokenize(`"string 123 ok"`)).toEqual([
{ kind: 'string', value: `"string 123 ok"`, location: { start: 0, end: 14 } },
{ kind: 'eof', value: '', location: { start: 15, end: 15 } }
])
})

Expand Down
15 changes: 13 additions & 2 deletions src/lexer/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,14 @@ export const lexerTokenKinds = <const>[

// special
'unknown',
'unterminated-string',
'unterminated-char',
'eof'
]
export type TokenKind = typeof lexerTokenKinds[number]

export const erroneousTokenKinds: TokenKind[] = ['unknown', 'unterminated-char', 'unterminated-string']

export interface ParseToken {
kind: TokenKind
value: string
Expand Down Expand Up @@ -266,6 +270,11 @@ const parseCharLiteral = (chars: string[], tokens: ParseToken[], pos: { pos: num
pos.pos++
const charLiteral: string[] = []
while (chars[pos.pos] !== quote) {
if (isNewline(chars[pos.pos]) || pos.pos === chars.length) {
pos.pos++
tokens.push(createToken('unterminated-char', quote + charLiteral.join(''), pos, start))
return true
}
charLiteral.push(chars[pos.pos])
pos.pos++
}
Expand All @@ -292,8 +301,10 @@ const parseStringLiteral = (chars: string[], tokens: ParseToken[], pos: { pos: n
pos.pos++
const stringLiteral: string[] = []
while (chars[pos.pos] !== quote) {
if (chars.length === pos.pos) {
throw Error(`no matching \`${quote}\``)
if (isNewline(chars[pos.pos]) || pos.pos === chars.length) {
pos.pos++
tokens.push(createToken('unterminated-string', quote + stringLiteral.join(''), pos, start))
return true
}
stringLiteral.push(chars[pos.pos])
pos.pos++
Expand Down

0 comments on commit 1658fa4

Please sign in to comment.