Skip to content

Commit 04a25ac

Browse files
authored
fix: Single-line if statements (#34)
1 parent e3b3b11 commit 04a25ac

File tree

2 files changed

+64
-25
lines changed

2 files changed

+64
-25
lines changed

src/parser.ts

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -530,16 +530,24 @@ function parseIf(tokens: Token[]): IfStatement {
530530
const test = parseExpression(tokens)
531531
consume(tokens, ')')
532532

533-
const consequent = parseBlock(tokens)
533+
let consequent: Statement
534+
if (tokens[0].value === '{') {
535+
consequent = parseBlock(tokens)
536+
} else {
537+
consequent = parseStatement(tokens)
538+
}
534539

535540
let alternate = null
536-
if (tokens[0] && tokens[0].value === 'else') {
541+
const elseToken = tokens[0]
542+
if (elseToken && elseToken.value === 'else') {
537543
consume(tokens, 'else')
538544

539545
if (tokens[0] && (tokens[0] as Token).value === 'if') {
540546
alternate = parseIf(tokens)
541-
} else {
547+
} else if (tokens[0].value === '{') {
542548
alternate = parseBlock(tokens)
549+
} else {
550+
alternate = parseStatement(tokens)
543551
}
544552
}
545553

@@ -689,6 +697,32 @@ function isVariable(tokens: Token[]): boolean {
689697
return tokens[i]?.type !== 'symbol'
690698
}
691699

700+
function parseStatement(tokens: Token[]): Statement {
701+
const token = tokens[0]
702+
let statement: Statement | null = null
703+
704+
if (token.value === '#') statement = parsePreprocessor(tokens)
705+
else if (token.value === 'struct') statement = parseStruct(tokens)
706+
else if (token.value === 'continue') statement = parseContinue(tokens)
707+
else if (token.value === 'break') statement = parseBreak(tokens)
708+
else if (token.value === 'discard') statement = parseDiscard(tokens)
709+
else if (token.value === 'return') statement = parseReturn(tokens)
710+
else if (token.value === 'if') statement = parseIf(tokens)
711+
else if (token.value === 'while') statement = parseWhile(tokens)
712+
else if (token.value === 'for') statement = parseFor(tokens)
713+
else if (token.value === 'do') statement = parseDoWhile(tokens)
714+
else if (token.value === 'switch') statement = parseSwitch(tokens)
715+
else if (token.value === 'precision') statement = parsePrecision(tokens)
716+
else if (isVariable(tokens)) statement = parseIndeterminate(tokens)
717+
else {
718+
const expression = parseExpression(tokens)
719+
consume(tokens, ';')
720+
statement = { type: 'ExpressionStatement', expression }
721+
}
722+
723+
return statement
724+
}
725+
692726
function parseStatements(tokens: Token[]): Statement[] {
693727
const body: Statement[] = []
694728
let scopeIndex = 0
@@ -699,29 +733,8 @@ function parseStatements(tokens: Token[]): Statement[] {
699733
scopeIndex += getScopeDelta(token)
700734
if (scopeIndex < 0) break
701735

702-
let statement: Statement | null = null
703-
704736
if (token.value === 'case' || token.value === 'default') break
705-
else if (token.value === '#') statement = parsePreprocessor(tokens)
706-
else if (token.value === 'struct') statement = parseStruct(tokens)
707-
else if (token.value === 'continue') statement = parseContinue(tokens)
708-
else if (token.value === 'break') statement = parseBreak(tokens)
709-
else if (token.value === 'discard') statement = parseDiscard(tokens)
710-
else if (token.value === 'return') statement = parseReturn(tokens)
711-
else if (token.value === 'if') statement = parseIf(tokens)
712-
else if (token.value === 'while') statement = parseWhile(tokens)
713-
else if (token.value === 'for') statement = parseFor(tokens)
714-
else if (token.value === 'do') statement = parseDoWhile(tokens)
715-
else if (token.value === 'switch') statement = parseSwitch(tokens)
716-
else if (token.value === 'precision') statement = parsePrecision(tokens)
717-
else if (isVariable(tokens)) statement = parseIndeterminate(tokens)
718-
else {
719-
const expression = parseExpression(tokens)
720-
consume(tokens, ';')
721-
statement = { type: 'ExpressionStatement', expression }
722-
}
723-
724-
body.push(statement)
737+
body.push(parseStatement(tokens))
725738
}
726739

727740
return body

tests/parser.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,32 @@ describe('parser', () => {
758758
type: 'IfStatement',
759759
},
760760
])
761+
762+
expect(parse('if (true) a = 1;').body).toStrictEqual<[IfStatement]>([
763+
{
764+
alternate: null,
765+
consequent: {
766+
expression: {
767+
left: {
768+
name: 'a',
769+
type: 'Identifier',
770+
},
771+
operator: '=',
772+
right: {
773+
type: 'Literal',
774+
value: '1',
775+
},
776+
type: 'AssignmentExpression',
777+
},
778+
type: 'ExpressionStatement',
779+
},
780+
test: {
781+
type: 'Literal',
782+
value: 'true',
783+
},
784+
type: 'IfStatement',
785+
},
786+
])
761787
})
762788

763789
it('parses while statements', () => {

0 commit comments

Comments
 (0)