Skip to content

Commit

Permalink
Parser: semicolon statement separation; trailing comma fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Jun 9, 2023
1 parent 819321e commit 35551fa
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 11 deletions.
2 changes: 1 addition & 1 deletion nois.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ statement ::= var-def | fn-def | type-def | return-stmt | expr
;
param ::= IDENTIFIER type-annot?
;
block ::= O-BRACE statement* C-BRACE
block ::= O-BRACE (statement (SEMI statement)* SEMI?)? C-BRACE
;
type-annot ::= COLON type-expr
;
Expand Down
4 changes: 3 additions & 1 deletion src/lexer/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const lexerTokenKinds = <const>[
'o-angle',
'c-angle',
'colon',
'semi',
'comma',
'equals',
'underscore',
Expand Down Expand Up @@ -90,6 +91,7 @@ export const constTokenKindMap: Map<TokenKind, string> = new Map([
['period', '.'],

['colon', ':'],
['semi', ';'],
['comma', ','],
['equals', '='],
['underscore', '_'],
Expand All @@ -98,7 +100,7 @@ export const constTokenKindMap: Map<TokenKind, string> = new Map([
/**
* Independent tokens are automatically advanced by parser by default
*/
export const independentTokenKinds: Set<TokenKind> = new Set(['newline', 'comment'])
export const independentTokenKinds: TokenKind[] = ['newline', 'comment']

export const isWhitespace = (char: string): boolean => char === ' ' || char === '\t'

Expand Down
5 changes: 3 additions & 2 deletions src/parser/parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ describe('parser', () => {
it('mismatch paren', () => {

const { errors } = parse('if a { b) }')
expect(errors.length).toEqual(3)
// TODO: reduce multiple errors on the same symbol to the last one
expect(errors.length).toEqual(2)
expect(errors[0]).toEqual({
'expected': ['c-brace'],
'expected': ['semi'],
'got': { 'kind': 'c-paren', 'location': { 'end': 8, 'start': 8 }, 'value': ')' }
})
})
Expand Down
17 changes: 10 additions & 7 deletions src/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class Parser {
this.events.push({ type: 'advance' })
this.pos++
// TODO: attach comments to the preceding tree instead
if (skipIndependent && !this.eof() && independentTokenKinds.has(this.tokens[this.pos].kind)) {
if (skipIndependent && !this.eof() && independentTokenKinds.some(t => t === this.tokens[this.pos].kind)) {
this.advance()
}
}
Expand Down Expand Up @@ -319,7 +319,7 @@ const parseConstrList = (parser: Parser): void => {
while (!parser.at('c-brace') && !parser.eof()) {
parseConstructor(parser)
if (!parser.at('c-brace')) {
parser.consume('comma')
parser.expect('comma')
}
}
parser.expect('c-brace')
Expand Down Expand Up @@ -540,7 +540,7 @@ const parseArgs = (parser: Parser): void => {
while (!parser.at('c-paren') && !parser.eof()) {
parseExpr(parser)
if (!parser.at('c-paren')) {
parser.consume('comma')
parser.expect('comma')
}
}
parser.expect('c-paren')
Expand Down Expand Up @@ -575,7 +575,7 @@ const parseLambdaParams = (parser: Parser): void => {
while (!parser.at('pipe') && !parser.eof()) {
parseParam(parser)
if (!parser.at('pipe')) {
parser.consume('comma')
parser.expect('comma')
}
}
parser.expect('pipe')
Expand Down Expand Up @@ -611,13 +611,16 @@ const parseParam = (parser: Parser): void => {
}

/**
* block ::= O-BRACE statement* C-BRACE
* block ::= O-BRACE (statement (SEMI statement)* SEMI?)? C-BRACE
*/
const parseBlock = (parser: Parser): void => {
const mark = parser.open()
parser.expect('o-brace')
while (parser.atAny(statementFirstTokens) && !parser.eof()) {
while (!parser.at('c-brace') && !parser.eof()) {
parseStatement(parser)
if (!parser.at('c-brace')) {
parser.expect('semi')
}
}
parser.expect('c-brace')
parser.close(mark, 'block')
Expand Down Expand Up @@ -654,7 +657,7 @@ const parseTypeParams = (parser: Parser): void => {
while (!parser.at('c-angle') && !parser.eof()) {
parseTypeExpr(parser)
if (!parser.at('c-angle')) {
parser.consume('comma')
parser.expect('comma')
}
}
parser.expect('c-angle')
Expand Down

0 comments on commit 35551fa

Please sign in to comment.