Skip to content

Commit

Permalink
Grammar improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Jun 4, 2023
1 parent 6cb4a57 commit bd964ba
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 59 deletions.
14 changes: 4 additions & 10 deletions src/grammar.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,23 @@ block ::= OPEN-BRACE statements CLOSE-BRACE
| OPEN-BRACE CLOSE-BRACE
;

expr ::= sub-expr expr_
expr ::= sub-expr infix-operator sub-expr
| sub-expr
;

expr_ ::= infix-operator sub-expr
;

sub-expr ::= unary-expr
| operand
// | paren-expr
;

unary-expr ::= prefix-op paren-expr
| paren-expr postfix-op
;

paren-expr ::= OPEN-PAREN expr CLOSE-PAREN
unary-expr ::= prefix-op operand
| operand postfix-op
;

operand ::= STRING
| CHAR
| NUMBER
| IDENTIFIER
| OPEN-PAREN expr CLOSE-PAREN
| type
| function-expr
| if-expr
Expand Down
31 changes: 9 additions & 22 deletions src/grammar.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,10 @@
"branches": [
[
"sub-expr",
"expr_"
],
[
"infix-operator",
"sub-expr"
]
]
},
{
"name": "expr_",
"branches": [
],
[
"infix-operator",
"sub-expr"
]
]
Expand All @@ -120,24 +112,14 @@
"branches": [
[
"prefix-op",
"paren-expr"
"operand"
],
[
"paren-expr",
"operand",
"postfix-op"
]
]
},
{
"name": "paren-expr",
"branches": [
[
"open-paren",
"expr",
"close-paren"
]
]
},
{
"name": "operand",
"branches": [
Expand All @@ -153,6 +135,11 @@
[
"identifier"
],
[
"open-paren",
"expr",
"close-paren"
],
[
"type"
],
Expand Down
63 changes: 46 additions & 17 deletions src/parser/parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,28 +62,57 @@ describe('parser', () => {
})
})

it('parse function-expr', () => {
const code = `(): Unit {}`
const rule = parse(code, 'function-expr')
it('parse unary-expr', () => {
const rule = parse('-3', 'unary-expr')
expect(compactToken(rule!)).toEqual({
'name': 'function-expr',
'name': 'unary-expr',
'nodes': [
{ 'name': 'open-paren', 'value': '(' },
{ 'name': 'close-paren', 'value': ')' },
{ 'name': 'colon', 'value': ':' },
{
'name': 'type',
'nodes': [
{ 'name': 'identifier', 'value': 'Unit' }
]
}, {
'name': 'block',
'nodes': [
{ 'name': 'open-brace', 'value': '{' },
{ 'name': 'close-brace', 'value': '}' }
]
'name': 'prefix-op',
'nodes': [{
'name': 'minus', 'value': '-'
}]
},
{
'name': 'operand',
'nodes': [{
'name': 'number', 'value': '3'
}]
}]
})
})

it('parse function-expr', () => {
const code = `(): Unit {}`
const rule = parse(code, 'expr')
expect(compactToken(rule!)).toEqual({
'name': 'expr', 'nodes': [{
'name': 'sub-expr', 'nodes': [{
'name': 'operand', 'nodes': [{
'name': 'function-expr',
'nodes': [
{ 'name': 'open-paren', 'value': '(' },
{ 'name': 'close-paren', 'value': ')' },
{ 'name': 'colon', 'value': ':' },
{
'name': 'type',
'nodes': [
{ 'name': 'identifier', 'value': 'Unit' }
]
},
{
'name': 'block',
'nodes': [
{ 'name': 'open-brace', 'value': '{' },
{ 'name': 'close-brace', 'value': '}' }
]
}
],
}]
}]
}]

})
})

})
39 changes: 29 additions & 10 deletions src/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,35 @@ import { LexerToken, LexerTokenName, TokenLocation } from '../lexer/lexer'
import { generateParsingTable } from './table'
import { readFileSync } from 'fs'
import { join } from 'path'
import { inspect } from 'util'

export type ParserTokenName
= 'program'
| 'statement'
| 'function-expr'
| 'params'
| 'params_'
| 'param'
| 'trailing-comma'
| 'block'
| 'block_'
export const parserTokenNames = <const>[
'program',
'statements',
'statement',
'variable-def',
'type-def',
'return-stmt',
'block',
'expr',
'expr_',
'sub-expr',
'unary-expr',
'paren-expr',
'operand',
'infix-operator',
'prefix-op',
'postfix-op',
'args',
'function-expr',
'params',
'param',
'trailing-comma',
'type',
'type-params',
'if-expr',
]
export type ParserTokenName = typeof parserTokenNames[number]

export interface ParserToken {
name: ParserTokenName,
Expand Down Expand Up @@ -58,6 +76,7 @@ export const generateTransforms = (tokens: LexerToken[], root: ParserTokenName =
} else {
const transform = table.get(<ParserTokenName>stack.at(-1)!)?.get(buffer[0].name)
if (!transform) {
console.debug(inspect({ chain }, { depth: null, colors: true }))
throw Error(`syntax error, expected ${stack.at(-1)}, got ${buffer[0].name}, at ${buffer[0].location.start}`)
}
chain.push(transform)
Expand Down

0 comments on commit bd964ba

Please sign in to comment.