diff --git a/compiler/parser/expr.v b/compiler/parser/expr.v index 255639da..aa7f989f 100644 --- a/compiler/parser/expr.v +++ b/compiler/parser/expr.v @@ -8,6 +8,9 @@ import compiler.ast import compiler.context fn (mut p Parser) parse_expr() ast.Expr { + if p.should_abort() { + return ast.empty_expr + } match p.tok.kind { .kw_if {} .kw_match {} diff --git a/compiler/parser/mod.v b/compiler/parser/mod.v index 7d37795a..a3396220 100644 --- a/compiler/parser/mod.v +++ b/compiler/parser/mod.v @@ -48,7 +48,6 @@ fn (mut p Parser) parse_file(filename string, is_root bool) { } p.advance(2) - for { p.file.stmts << p.parse_stmt() if p.should_abort() { diff --git a/compiler/parser/stmt.v b/compiler/parser/stmt.v index 375db2a5..ec42f9ea 100644 --- a/compiler/parser/stmt.v +++ b/compiler/parser/stmt.v @@ -8,18 +8,32 @@ import compiler.ast import compiler.context fn (mut p Parser) parse_block() []ast.Stmt { + if p.tok.kind == .lbrace && p.next_tok.kind == .rbrace { + // empty block: `{}` + p.advance(2) + return [] + } + old_inside_local_scope := p.inside_local_scope defer { p.inside_local_scope = old_inside_local_scope } p.inside_local_scope = true + mut is_finished := false mut stmts := []ast.Stmt{} + lbrace_pos := p.tok.pos p.expect(.lbrace) - for !p.accept(.rbrace) { + for { stmts << p.parse_stmt() - if p.should_abort() { + is_finished = p.accept(.rbrace) + if is_finished || p.should_abort() { break } } + if !is_finished && !p.abort { + // we give an error because the block has not been finished (`}` was not found), + // but it has not been aborted (due to poor formation of expressions or statements) + context.error('unfinished block, expected `}` and found ${p.tok}', lbrace_pos) + } return stmts } diff --git a/compiler/tokenizer/token.v b/compiler/tokenizer/token.v index f52a7447..5cde76d8 100644 --- a/compiler/tokenizer/token.v +++ b/compiler/tokenizer/token.v @@ -130,7 +130,7 @@ fn build_keys() map[string]Kind { fn build_token_str() []string { mut s := []string{len: int(Kind._end_)} s[Kind.unknown] = 'unknown' - s[Kind.eof] = 'eof' + s[Kind.eof] = 'end of file' s[Kind.ident] = 'identifier' s[Kind.number] = 'number' s[Kind.string] = 'string'