aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorJason Kercher <JKercher@JSM.lcl>2022-03-10 09:34:48 -0500
committerJason Kercher <JKercher@JSM.lcl>2022-03-10 09:34:48 -0500
commitb91c0ec7154008b0b84973054e4487ed4d733aba (patch)
treecdbc19eeeb3aa9160880e1e62462b9915c60660d /src/parser.cpp
parentbad295cf695e623591f737fb68556ea0a76a53ce (diff)
parentdc8d28c383a404d01dcbcb65ba84ff814da9424e (diff)
Merge remote-tracking branch 'upstream/master' into os2_linux
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp113
1 files changed, 64 insertions, 49 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 8a7ab2d20..94a585f35 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -1538,7 +1538,7 @@ void fix_advance_to_next_stmt(AstFile *f) {
Token expect_closing(AstFile *f, TokenKind kind, String context) {
if (f->curr_token.kind != kind &&
f->curr_token.kind == Token_Semicolon &&
- f->curr_token.string == "\n") {
+ (f->curr_token.string == "\n" || f->curr_token.kind == Token_EOF)) {
Token tok = f->prev_token;
tok.pos.column += cast(i32)tok.string.len;
syntax_error(tok, "Missing ',' before newline in %.*s", LIT(context));
@@ -1560,6 +1560,7 @@ void assign_removal_flag_to_semicolon(AstFile *f) {
switch (curr_token->kind) {
case Token_CloseBrace:
case Token_CloseParen:
+ case Token_EOF:
ok = true;
break;
}
@@ -3015,64 +3016,62 @@ i32 token_precedence(AstFile *f, TokenKind t) {
Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
Ast *expr = parse_unary_expr(f, lhs);
- for (i32 prec = token_precedence(f, f->curr_token.kind); prec >= prec_in; prec--) {
- for (;;) {
- Token op = f->curr_token;
- i32 op_prec = token_precedence(f, op.kind);
- if (op_prec != prec) {
- // NOTE(bill): This will also catch operators that are not valid "binary" operators
- break;
+ for (;;) {
+ Token op = f->curr_token;
+ i32 op_prec = token_precedence(f, op.kind);
+ if (op_prec < prec_in) {
+ // NOTE(bill): This will also catch operators that are not valid "binary" operators
+ break;
+ }
+ Token prev = f->prev_token;
+ switch (op.kind) {
+ case Token_if:
+ case Token_when:
+ if (prev.pos.line < op.pos.line) {
+ // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
+ goto loop_end;
}
- Token prev = f->prev_token;
+ break;
+ }
+ expect_operator(f); // NOTE(bill): error checks too
+
+ if (op.kind == Token_Question) {
+ Ast *cond = expr;
+ // Token_Question
+ Ast *x = parse_expr(f, lhs);
+ Token token_c = expect_token(f, Token_Colon);
+ Ast *y = parse_expr(f, lhs);
+ expr = ast_ternary_if_expr(f, x, cond, y);
+ } else if (op.kind == Token_if || op.kind == Token_when) {
+ Ast *x = expr;
+ Ast *cond = parse_expr(f, lhs);
+ Token tok_else = expect_token(f, Token_else);
+ Ast *y = parse_expr(f, lhs);
+
switch (op.kind) {
case Token_if:
+ expr = ast_ternary_if_expr(f, x, cond, y);
+ break;
case Token_when:
- if (prev.pos.line < op.pos.line) {
- // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
- goto loop_end;
- }
+ expr = ast_ternary_when_expr(f, x, cond, y);
break;
}
- expect_operator(f); // NOTE(bill): error checks too
-
- if (op.kind == Token_Question) {
- Ast *cond = expr;
- // Token_Question
- Ast *x = parse_expr(f, lhs);
- Token token_c = expect_token(f, Token_Colon);
- Ast *y = parse_expr(f, lhs);
- expr = ast_ternary_if_expr(f, x, cond, y);
- } else if (op.kind == Token_if || op.kind == Token_when) {
- Ast *x = expr;
- Ast *cond = parse_expr(f, lhs);
- Token tok_else = expect_token(f, Token_else);
- Ast *y = parse_expr(f, lhs);
-
- switch (op.kind) {
- case Token_if:
- expr = ast_ternary_if_expr(f, x, cond, y);
- break;
- case Token_when:
- expr = ast_ternary_when_expr(f, x, cond, y);
- break;
- }
+ } else {
+ Ast *right = parse_binary_expr(f, false, op_prec+1);
+ if (right == nullptr) {
+ syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string));
+ }
+ if (op.kind == Token_or_else) {
+ // NOTE(bill): easier to handle its logic different with its own AST kind
+ expr = ast_or_else_expr(f, expr, op, right);
} else {
- Ast *right = parse_binary_expr(f, false, prec+1);
- if (right == nullptr) {
- syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string));
- }
- if (op.kind == Token_or_else) {
- // NOTE(bill): easier to handle its logic different with its own AST kind
- expr = ast_or_else_expr(f, expr, op, right);
- } else {
- expr = ast_binary_expr(f, op, expr, right);
- }
+ expr = ast_binary_expr(f, op, expr, right);
}
-
- lhs = false;
}
- loop_end:;
+
+ lhs = false;
}
+ loop_end:;
return expr;
}
@@ -5721,6 +5720,22 @@ ParseFileError parse_packages(Parser *p, String init_filename) {
error_line("Expected either a directory or a .odin file, got '%.*s'\n", LIT(init_filename));
return ParseFile_WrongExtension;
}
+ } else if (init_fullpath.len != 0) {
+ String path = init_fullpath;
+ if (path[path.len-1] == '/') {
+ path.len -= 1;
+ }
+ if ((build_context.command_kind & Command__does_build) &&
+ build_context.build_mode == BuildMode_Executable) {
+ String short_path = filename_from_path(path);
+ char *cpath = alloc_cstring(heap_allocator(), short_path);
+ defer (gb_free(heap_allocator(), cpath));
+
+ if (gb_file_exists(cpath)) {
+ error_line("Please specify the executable name with -out:<string> as a directory exists with the same name in the current working directory");
+ return ParseFile_DirectoryAlreadyExists;
+ }
+ }
}