Skip to content

Commit

Permalink
Parser: fn-def type-params; each rule is a tree; improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Jun 8, 2023
1 parent e9301b0 commit 718b478
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 28 deletions.
2 changes: 1 addition & 1 deletion nois.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ statement ::= var-def | fn-def | type-def | return-stmt | expr
;
var-def ::= LET-KEYWORD IDENTIFIER type-annot? EQUALS expr
;
fn-def ::= FN-KEYWORD IDENTIFIER O-PAREN params? C-PAREN type-annot? block?
fn-def ::= FN-KEYWORD IDENTIFIER type-params? O-PAREN params? C-PAREN type-annot? block?
;
type-def ::= TYPE-KEYWORD type-expr (constr-params | constr-list)
;
Expand Down
11 changes: 5 additions & 6 deletions src/parser/parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('parser', () => {
'fn-def': [
{ 'fn-keyword': 'fn' },
{ 'identifier': 'main' },
{ 'o-paren': '(' }, { 'c-paren': ')' },
{ 'params': [{ 'o-paren': '(' }, { 'c-paren': ')' }] },
{ 'block': [{ 'o-brace': '{' }, { 'c-brace': '}' }] }
]
}]
Expand All @@ -30,7 +30,7 @@ describe('parser', () => {
})
})

describe('parse fn-def', () => {
describe('parse var-def', () => {
it('miss identifier', () => {
const { errors } = parse('let = 4')
expect(errors.length).toEqual(1)
Expand Down Expand Up @@ -96,11 +96,10 @@ describe('parser', () => {
it('mismatch paren', () => {

const { errors } = parse('if a { b) }')
expect(errors.length).toEqual(1)
expect(errors.length).toEqual(3)
expect(errors[0]).toEqual({
'expected': [],
'got': { 'kind': 'c-paren', 'location': { 'end': 8, 'start': 8 }, 'value': ')' },
'message': 'expected operand'
'expected': ['c-brace'],
'got': { 'kind': 'c-paren', 'location': { 'end': 8, 'start': 8 }, 'value': ')' }
})
})

Expand Down
45 changes: 24 additions & 21 deletions src/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,10 @@ const parseStatement = (parser: Parser): void => {
parseTypeDef(parser)
} else if (parser.at('return-keyword')) {
parseReturnStmt(parser)
} else {
} else if (parser.atAny(exprFirstTokens)) {
parseExpr(parser)
} else {
parser.advanceWithError('expected statement')
}

parser.close(mark, 'statement')
Expand All @@ -254,17 +256,18 @@ const parseVarDef = (parser: Parser): void => {
}

/**
* fn-def ::= FN-KEYWORD IDENTIFIER O-PAREN params? C-PAREN type-annot? block?
* fn-def ::= FN-KEYWORD IDENTIFIER type-params? O-PAREN params? C-PAREN type-annot? block?
*/
const parseFnDef = (parser: Parser): void => {
const mark = parser.open()
parser.expect('fn-keyword')
parser.expect('identifier')
parser.expect('o-paren')
if (!parser.at('c-paren')) {
if (parser.at('o-angle')) {
parseTypeParams(parser)
}
if (parser.at('o-paren')) {
parseParams(parser)
}
parser.expect('c-paren')
if (parser.at('colon')) {
parseTypeAnnot(parser)
}
Expand Down Expand Up @@ -477,48 +480,48 @@ const parseInfixOp = (parser: Parser): void => {
*/
const parsePrefixOp = (parser: Parser): void => {
const mark = parser.open()
const m = parser.open()

if (parser.consume('plus')) {
parser.close(mark, 'add-op')
return
}
if (parser.consume('minus')) {
parser.close(mark, 'sub-op')
return
}
if (parser.consume('excl')) {
parser.close(mark, 'not-op')
return
}
if (parser.consume('period')) {
parser.close(m, 'add-op')
} else if (parser.consume('minus')) {
parser.close(m, 'sub-op')
} else if (parser.consume('excl')) {
parser.close(m, 'not-op')
} else if (parser.consume('period')) {
parser.advance()
parser.close(mark, 'spread-op')
return
parser.close(m, 'spread-op')
} else {
parser.advanceWithError('expected prefix operator')
}

parser.advanceWithError('expected prefix operator')
parser.close(mark, 'prefix-op')
}

/**
* postfix-op ::= call-op
*/
const parsePostfixOp = (parser: Parser): void => {
const mark = parser.open()
if (parser.at('o-paren')) {
parseCallOp(parser)
} else {
parser.advanceWithError('expected postfix operator')
}
parser.close(mark, 'postfix-op')
}

/**
* call-op ::= args
*/
const parseCallOp = (parser: Parser): void => {
const mark = parser.open()
if (parser.at('o-paren')) {
parseArgs(parser)
} else {
parser.advanceWithError('expected call operator')
}
parser.close(mark, 'call-op')
}

/**
Expand Down Expand Up @@ -594,7 +597,7 @@ const parseParam = (parser: Parser): void => {
const parseBlock = (parser: Parser): void => {
const mark = parser.open()
parser.expect('o-brace')
while (!parser.at('c-brace') && !parser.eof()) {
while (parser.atAny(statementFirstTokens) && !parser.eof()) {
parseStatement(parser)
}
parser.expect('c-brace')
Expand Down

0 comments on commit 718b478

Please sign in to comment.