Skip to content

Commit

Permalink
updated if and match statements
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiosvm committed Aug 18, 2023
1 parent d7b85d0 commit 31cbea4
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 83 deletions.
119 changes: 119 additions & 0 deletions docs/grammar.ebnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
chunk ::= statement* EOF

statement ::= import_statement
| variable_declaration ';'
| assign_call ';'
| struct_declaration
| function_declaration
| delete_statement
| if_statement
| match_statement
| loop_statement
| while_statement
| for_statement
| break_statement
| return_statement
| block

import_statement ::= 'import' name ( 'as' name )? ';'
| 'import' STRING 'as' name ';'
| 'import' '{' name ( ',' name )* '}' 'from' ( name | STRING ) ';'

variable_declaration ::= 'let' name '=' expression
| 'mut' name ( '=' expression )?
| ( 'let' | 'mut' ) '[' '_' | name ( ',' '_' | name )* ']' '=' expression
| ( 'let' | 'mut' ) '{' name ( ',' name )* '}' '=' expression

assign_call ::= name subscript* assign_op expression
| name subscript* ( '++' | '--' )
| name subscript* '[' ']' '=' expression
| name subscript* subscript '=' expression
| name ( subscript | call )* call

struct_declaration ::= 'struct' name '{' ( string | name ( ',' string | name )* )? '}'

function_declaration ::= 'fn' name '(' ( 'mut'? name ( ',' 'mut'? name )* )? ')' ( '=>' expression | block )

delete_statement ::= 'del' name subscript* '[' expression ']' ';'

if_statement ::= ( 'if' | 'if!' ) '(' ( ( variable_declaration | assign_call ) ';' )? expression ')'
statement ( 'else' statement )?

match_statement ::= 'match' '(' ( ( variable_declaration | assign_call ) ';' )? expression ')'
'{' ( expression '=>' statement )+ ( '_' '=>' statement )? '}'

loop_statement ::= 'loop' statement

while_statement ::= ( 'while' | 'while!' ) '(' expression ')' statement
| 'do' statement ( 'while' | 'while!' ) '(' expression ')' ';'

for_statement ::= 'for' '(' ( variable_declaration | assign_call )? ';' expression? ';' assign_call? ')' statement
| 'foreach' '(' name 'in' expression ')' statement

break_statement ::= ( 'break' | 'continue' ) ';'

return_statement ::= 'return' expression? ';'

block ::= '{' stmt* '}'

assign_op ::= '=' | '|=' | '^=' | '&=' | '<<=' | '>>='
| '+=' | '-=' | '*=' | '/=' | '~/=' | '%='

subscript ::= '[' expression ']' | '.' name

call ::= '(' ( expression ( ',' expression )* )? ')'

expression ::= and_expression ( '||' and_expression )*

and_expression ::= equal_expression ( '&&' equal_expression )*

equal_expression ::= comp_expression ( ( '==' | '!=' ) comp_expression )*

comp_expression ::= bor_expression ( ( '>' | '>=' | '<' | '<=' ) bor_expression )*

bor_expression ::= bxor_expression ( '|' bxor_expression )*

bxor_expression ::= band_expression ( '^' band_expression )*

band_expression ::= shift_expression ( '&' shift_expression )*

shift_expression ::= range_expression ( ( '<<' | '>>' ) range_expression )*

range_expression ::= add_expression ( '..' add_expression )?

add_expression ::= mul_expression ( ( '+' | '-' ) mul_expression )*

mul_expression ::= unary_expression ( ( '*' | '/' | '~/' | '%' ) unary_expression )*

unary_expression ::= ( '-' | '!' | '~' ) unary_expression | primary_expression

primary_expression ::= literal
| array_constructor
| struct_constructor
| anonymous_struct
| anonymous_function
| if_expression
| match_expression
| subscript_call
| group_expression

literal ::= 'nil' | 'false' | 'true' | number | string

array_constructor ::= '[' ( expression ( ',' expression )* )? ']'

struct_constructor ::= '{' ( string | name ':' expression ( ',' string | name ':' expression )* )? '}'

anonymous_struct ::= 'struct' '{' ( string | name ( ',' string | name )* )? '}'

anonymous_function ::= '|' ( 'mut'? name ( ',' 'mut'? name )* )? '|' ( '=>' expression | block )
| '||' ( '=>' expression | block )

if_expression ::= ( 'if' | 'if!' ) '(' expression ')' expression 'else' expression

match_expression ::= 'match' '(' expression ')' '{' expression '=>' expression ( ',' expression '=>' expression )*
',' '_' '=>' expression '}'

subscript_call ::= name ( subscript | call )* ( '{' ( expression ( ',' expression )* )? '}' )?

group_expression ::= '(' expression ')'
10 changes: 6 additions & 4 deletions docs/grammar.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ In addition, Hook uses a special token to indicate the end of a file. This token

The complete syntactic grammar of Hook is defined by the following EBNF grammar:

```
```ebnf
chunk ::= statement* EOF
statement ::= import_statement
Expand Down Expand Up @@ -218,16 +218,18 @@ function_declaration ::= 'fn' name '(' ( 'mut'? name ( ',' 'mut'? name )* )? ')'
delete_statement ::= 'del' name subscript* '[' expression ']' ';'
if_statement ::= ( 'if' | 'if!' ) '(' ( variable_declaration ';' )? expression ')' statement ( 'else' statement )?
if_statement ::= ( 'if' | 'if!' ) '(' ( ( variable_declaration | assign_call ) ';' )? expression ')'
statement ( 'else' statement )?
match_statement ::= 'match' '(' ( variable_declaration ';' )? expression ')' '{' ( expression '=>' statement )+ ( '_' '=>' statement )? '}'
match_statement ::= 'match' '(' ( ( variable_declaration | assign_call ) ';' )? expression ')'
'{' ( expression '=>' statement )+ ( '_' '=>' statement )? '}'
loop_statement ::= 'loop' statement
while_statement ::= ( 'while' | 'while!' ) '(' expression ')' statement
| 'do' statement ( 'while' | 'while!' ) '(' expression ')' ';'
for_statement ::= 'for' '(' variable_declaration | assign_call? ';' expression? ';' assign_call? ')' statement
for_statement ::= 'for' '(' ( variable_declaration | assign_call )? ';' expression? ';' assign_call? ')' statement
| 'foreach' '(' name 'in' expression ')' statement
break_statement ::= ( 'break' | 'continue' ) ';'
Expand Down
79 changes: 0 additions & 79 deletions docs/grammar.txt

This file was deleted.

14 changes: 14 additions & 0 deletions src/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,13 @@ static void compile_if_statement(Compiler *comp, bool not)
compile_variable_declaration(comp);
consume(comp, TOKEN_SEMICOLON);
}
else if (match(scan, TOKEN_NAME))
{
Token tk = scan->token;
scanner_next_token(scan);
compile_assign_statement(comp, &tk);
consume(comp, TOKEN_SEMICOLON);
}
compile_expression(comp);
consume(comp, TOKEN_RPAREN);
HkOpCode op = not ? HK_OP_JUMP_IF_TRUE : HK_OP_JUMP_IF_FALSE;
Expand Down Expand Up @@ -1311,6 +1318,13 @@ static void compile_match_statement(Compiler *comp)
compile_variable_declaration(comp);
consume(comp, TOKEN_SEMICOLON);
}
else if (match(scan, TOKEN_NAME))
{
Token tk = scan->token;
scanner_next_token(scan);
compile_assign_statement(comp, &tk);
consume(comp, TOKEN_SEMICOLON);
}
compile_expression(comp);
consume(comp, TOKEN_RPAREN);
consume(comp, TOKEN_LBRACE);
Expand Down
6 changes: 6 additions & 0 deletions tests/if_statement_var_declaration_test.hk
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ if (mut { ok, err } = baz(); err) {
} else {
println(ok);
}

mut result;
if (result = baz(); result.err) {
println(result.err);
}
println(result.ok);
8 changes: 8 additions & 0 deletions tests/match_statement_var_declaration_test.hk
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,11 @@ match (let { lvl, msg } = error("error message"); lvl) {
"error" => println(msg);
_ => println("unknown log level");
}

mut result;
match (result = info("info message"); result.lvl) {
"info" => println(result.msg);
"warn" => println(result.msg);
"error" => println(result.msg);
_ => println("unknown log level");
}

0 comments on commit 31cbea4

Please sign in to comment.