aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-01-01 20:41:10 +0000
committerGinger Bill <bill@gingerbill.org>2017-01-01 20:41:10 +0000
commit9202bd1b0640737ce9d843f8d308debe45fc9a90 (patch)
treef3153718034b50a3e2bcdd2d3608f30df7622958 /src/parser.c
parenta48e0c7179cfe78f3163a3e471f7401502d8c437 (diff)
Nearly finished Jai-like declarations
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c137
1 files changed, 81 insertions, 56 deletions
diff --git a/src/parser.c b/src/parser.c
index 1a659da7a..8546e692a 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -281,15 +281,6 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
AstNodeArray values; \
u64 tags; \
}) \
- AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \
- AstNode *name; \
- AstNode *type; \
- AstNode *body; \
- u64 tags; \
- String foreign_name; \
- String link_name; \
- AstNode *note; \
- }) \
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
Token token, filepath; \
String base_dir; \
@@ -303,6 +294,10 @@ AST_NODE_KIND(_DeclEnd, "", i32) \
bool is_using; \
}) \
AST_NODE_KIND(_TypeBegin, "", i32) \
+ AST_NODE_KIND(HelperType, "type", struct { \
+ Token token; \
+ AstNode *type; \
+ }) \
AST_NODE_KIND(ProcType, "procedure type", struct { \
Token token; \
AstNodeArray params; \
@@ -501,8 +496,6 @@ Token ast_node_token(AstNode *node) {
return node->GenericDecl.token;
case AstNode_ValueDecl:
return ast_node_token(node->ValueDecl.names.e[0]);
- case AstNode_ProcDecl:
- return ast_node_token(node->ProcDecl.name);
case AstNode_ForeignLibrary:
return node->ForeignLibrary.token;
@@ -519,6 +512,10 @@ Token ast_node_token(AstNode *node) {
return ast_node_token(node->Field.type);
}
}
+
+
+ case AstNode_HelperType:
+ return node->HelperType.token;
case AstNode_ProcType:
return node->ProcType.token;
case AstNode_PointerType:
@@ -969,6 +966,15 @@ AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, bool is_using
return result;
}
+
+AstNode *make_helper_type(AstFile *f, Token token, AstNode *type) {
+ AstNode *result = make_node(f, AstNode_HelperType);
+ result->HelperType.token = token;
+ result->HelperType.type = type;
+ return result;
+}
+
+
AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results, u64 tags, ProcCallingConvention calling_convention) {
AstNode *result = make_node(f, AstNode_ProcType);
result->ProcType.token = token;
@@ -979,17 +985,6 @@ AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArr
return result;
}
-AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) {
- AstNode *result = make_node(f, AstNode_ProcDecl);
- result->ProcDecl.name = name;
- result->ProcDecl.type = proc_type;
- result->ProcDecl.body = body;
- result->ProcDecl.tags = tags;
- result->ProcDecl.foreign_name = foreign_name;
- result->ProcDecl.link_name = link_name;
- return result;
-}
-
AstNode *make_pointer_type(AstFile *f, Token token, AstNode *type) {
AstNode *result = make_node(f, AstNode_PointerType);
result->PointerType.token = token;
@@ -1264,6 +1259,52 @@ Token expect_closing(AstFile *f, TokenKind kind, String context) {
return expect_token(f, kind);
}
+bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
+ if (s == NULL) {
+ return false;
+ }
+
+ switch (s->kind) {
+ case AstNode_HelperType:
+ return is_semicolon_optional_for_node(f, s->HelperType.type);
+
+ case AstNode_StructType:
+ case AstNode_UnionType:
+ case AstNode_RawUnionType:
+ case AstNode_EnumType:
+ return true;
+ case AstNode_ProcLit:
+ return true;
+
+ case AstNode_ValueDecl:
+ if (!s->ValueDecl.is_var) {
+ if (s->ValueDecl.values.count > 0) {
+ AstNode *last = s->ValueDecl.values.e[s->ValueDecl.values.count-1];
+ return is_semicolon_optional_for_node(f, last);
+ }
+ }
+ break;
+
+ case AstNode_GenericDecl:
+ if (s->GenericDecl.close.kind == Token_CloseBrace) {
+ return true;
+ } else if (s->GenericDecl.token.kind == Token_type) {
+ if (f->prev_token.kind == Token_CloseBrace) {
+ return true;
+ }
+ }
+ break;
+
+ case AstNode_TypeSpec:
+ if (f->prev_token.kind == Token_CloseBrace) {
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
void expect_semicolon(AstFile *f, AstNode *s) {
if (allow_token(f, Token_Semicolon)) {
return;
@@ -1277,24 +1318,8 @@ void expect_semicolon(AstFile *f, AstNode *s) {
if (s != NULL) {
if (prev_token.pos.line != f->curr_token.pos.line) {
- switch (s->kind) {
- case AstNode_ProcDecl:
+ if (is_semicolon_optional_for_node(f, s)) {
return;
- case AstNode_GenericDecl:
- if (s->GenericDecl.close.kind == Token_CloseBrace) {
- return;
- } else if (s->GenericDecl.token.kind == Token_type) {
- if (f->prev_token.kind == Token_CloseBrace) {
- return;
- }
- }
- break;
-
- case AstNode_TypeSpec:
- if (f->prev_token.kind == Token_CloseBrace) {
- return;
- }
- break;
}
} else {
switch (s->kind) {
@@ -1319,7 +1344,6 @@ AstNode * parse_proc_type(AstFile *f, String *foreign_name_, String *link_nam
AstNodeArray parse_stmt_list(AstFile *f);
AstNode * parse_stmt(AstFile *f);
AstNode * parse_body(AstFile *f);
-AstNode * parse_proc_decl(AstFile *f);
void parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results);
@@ -1571,6 +1595,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
AstNodeArray parse_lhs_expr_list(AstFile *f);
AstNodeArray parse_rhs_expr_list(AstFile *f);
AstNode * parse_simple_stmt (AstFile *f);
+AstNode * parse_type (AstFile *f);
AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
if (statement == NULL) {
@@ -1745,10 +1770,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
String foreign_name = {0};
String link_name = {0};
AstNode *type = parse_proc_type(f, &foreign_name, &link_name);
+ u64 tags = type->ProcType.tags;
if (f->curr_token.kind == Token_OpenBrace) {
- u64 tags = type->ProcType.tags;
-
if ((tags & ProcTag_foreign) != 0) {
syntax_error(token, "A procedure tagged as `#foreign` cannot have a body");
}
@@ -1760,6 +1784,13 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
return make_proc_lit(f, type, body, tags, foreign_name, link_name);
}
+ if ((tags & ProcTag_foreign) != 0) {
+ return make_proc_lit(f, type, NULL, tags, foreign_name, link_name);
+ }
+ if ((tags & ProcTag_link_name) != 0) {
+ syntax_error(token, "A procedure typed cannot be tagged with `#link_name`");
+ }
+
return type;
}
@@ -1932,7 +1963,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
return operand;
}
-AstNode *parse_type(AstFile *f);
AstNode *parse_unary_expr(AstFile *f, bool lhs) {
switch (f->curr_token.kind) {
@@ -2240,17 +2270,6 @@ PARSE_SPEC_PROC(parse_include_spec) {
AstNode *parse_decl(AstFile *f) {
switch (f->curr_token.kind) {
- // case Token_var:
- // case Token_const:
- // return parse_generic_decl(f, f->curr_token.kind, parse_value_spec);
-
- case Token_type:
- return parse_generic_decl(f, f->curr_token.kind, parse_type_spec);
-
- case Token_proc:
- // TODO(bill): Should I allow procedures to use the generic declaration syntax?
- return parse_proc_decl(f);
-
case Token_import:
return parse_generic_decl(f, f->curr_token.kind, parse_import_spec);
case Token_include:
@@ -2504,6 +2523,12 @@ AstNode *parse_identifier_or_type(AstFile *f) {
return e;
}
+ case Token_type: {
+ Token token = expect_token(f, Token_type);
+ AstNode *type = parse_type(f);
+ return make_helper_type(f, token, type);
+ }
+
case Token_Pointer: {
Token token = expect_token(f, Token_Pointer);
AstNode *elem = parse_type(f);
@@ -2681,7 +2706,7 @@ AstNode *parse_body(AstFile *f) {
}
-
+/*
AstNode *parse_proc_decl(AstFile *f) {
if (look_ahead_token_kind(f, 1) == Token_OpenParen) {
// NOTE(bill): It's an anonymous procedure
@@ -2720,7 +2745,7 @@ AstNode *parse_proc_decl(AstFile *f) {
}
return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
-}
+} */
AstNode *parse_if_stmt(AstFile *f) {
if (f->curr_proc == NULL) {