diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-03-26 23:13:29 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-03-26 23:14:04 +0300 |
| commit | 9fb179ab999c3b98caabca09b30c409dc5dd3b3d (patch) | |
| tree | 087f849f78028950885b46fbbe1bae35f9c1a908 /src | |
| parent | 373728f324b82d305748cfe3c853053fe2a9f761 (diff) | |
| download | ek-9fb179ab999c3b98caabca09b30c409dc5dd3b3d.tar.gz ek-9fb179ab999c3b98caabca09b30c409dc5dd3b3d.zip | |
start enums
Diffstat (limited to 'src')
| -rw-r--r-- | src/actualize.c | 205 | ||||
| -rw-r--r-- | src/ast.c | 135 | ||||
| -rw-r--r-- | src/debug.c | 2 | ||||
| -rw-r--r-- | src/gen_lexer.h | 497 | ||||
| -rw-r--r-- | src/lexer.l | 1 | ||||
| -rw-r--r-- | src/parser.y | 5 | ||||
| -rw-r--r-- | src/source.mk | 2 |
7 files changed, 269 insertions, 578 deletions
diff --git a/src/actualize.c b/src/actualize.c index 8424c52..8aec279 100644 --- a/src/actualize.c +++ b/src/actualize.c @@ -84,6 +84,32 @@ static struct ast_node *void_type() return void_type; } +static struct ast_node *i64_type() +{ + char *i64_str = strdup("i64"); + if (!i64_str) { + internal_error("couldn't allocate i64 string"); + return NULL; + } + + struct ast_node *i64_id = gen_id(i64_str); + if (!i64_id) { + internal_error("couldn't allocate i64 id"); + free(i64_str); + return NULL; + } + + struct ast_node *i64_type = gen_type(AST_TYPE_ID, i64_id, NULL, NULL); + if (!i64_type) { + internal_error("couldn't allocate i64 type"); + destroy_ast_node(i64_id); + return NULL; + } + + i64_type->type = i64_type; + return i64_type; +} + static int push_defer(struct act_state *state, struct ast_node *expr) { struct act_stack *new = calloc(1, sizeof(struct act_stack)); @@ -306,7 +332,6 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node) } case AST_STRUCT: { - /* TODO: should structs be their own 'thing'? */ ret |= scope_add_type(scope, node); break; } @@ -570,18 +595,6 @@ struct ast_node *extract_template(struct ast_node *type) return extract_template(type->_type.next); } -struct ast_node *extract_base(struct ast_node *type) -{ - if (!type) - return 0; - - assert(type->node_type == AST_TYPE); - if (is_templateable(type)) - return type; - - return extract_base(type->_type.next); -} - static void actualize_template_types(struct ast_node *params, struct ast_node *args) { @@ -1146,24 +1159,23 @@ static int actualize_type(struct act_state *state, assert(exists->node_type == AST_ALIAS || exists->node_type == AST_TEMPLATE || exists->node_type == AST_STRUCT - || exists->node_type == AST_ENUM); + || exists->node_type == AST_ENUM + || exists->node_type == AST_UNION); /* actualize whatever type we have on demand, either alias or * template */ if (!ast_flags(exists, AST_FLAG_ACTUAL)) if (actualize(state, exists->scope, exists)) EXIT_ACT(-1); + assert(type->_type.next == NULL); + destroy_ast_node(type->_type.id); if (exists->node_type == AST_ALIAS) { /* TODO: check if this is good enough */ - destroy_ast_node(type->_type.id); - assert(type->_type.next == NULL); type->_type.kind = AST_TYPE_ALIAS; type->_type.alias.alias = exists; type->_type.alias.actual = exists->_alias.type; } else if (exists->node_type == AST_TEMPLATE) { - destroy_ast_node(type->_type.id); - assert(type->_type.next == NULL); type->_type.kind = AST_TYPE_TEMPLATE; type->_type.template.template = exists; /* this should be populated later */ @@ -1171,16 +1183,23 @@ static int actualize_type(struct act_state *state, } else if (exists->node_type == AST_STRUCT) { /* I think, will still have to TODO: check */ - destroy_ast_node(type->_type.id); - assert(type->_type.next == NULL); type->_type.kind = AST_TYPE_STRUCT; - type->_type.struc.struc = clone_ast_node( - exists->_struct.id); + type->_type.struc.id = + clone_ast_node(exists->_struct.id); /* should be populated later */ type->_type.struc.impls = NULL; } + else if (exists->node_type == AST_ENUM) { + type->_type.kind = AST_TYPE_ENUM; + type->_type.enu.id = clone_ast_node(exists->_enum.id); + type->_type.enu.type = exists->_enum.type; + } + else if (exists->node_type == AST_UNION) { + type->_type.kind = AST_TYPE_UNION; + type->_type.unio.id = clone_ast_node(exists->_union.id); + type->_type.unio.impls = NULL; + } - /* TODO: what about enums? */ break; } @@ -1236,8 +1255,8 @@ static int actualize_type(struct act_state *state, } case AST_TYPE_STRUCT: { - struct ast_node *struc = type->_type.struc.struc; - struct ast_node *exists = file_scope_resolve_type(scope, struc); + struct ast_node *id = type->_type.struc.id; + struct ast_node *exists = file_scope_resolve_type(scope, id); if (!exists || exists->node_type != AST_STRUCT) { semantic_error(scope->fctx, type, "no such struct"); EXIT_ACT(-1); @@ -1362,40 +1381,6 @@ static int pointer_conversion(struct ast_node *a, struct ast_node *b) return 0; } -static int check_impls(struct scope *scope, struct ast_node *target, - struct ast_node *exists) -{ - struct ast_node *args = target->_type.struc.impls; - struct ast_node *params = exists->_struct.generics; - while (args && params) { - assert(params->node_type == AST_ALIAS); - assert(args->node_type == AST_TYPE); - - struct ast_node *alias_actual = params->_alias.type; - if (!implements(scope, args, alias_actual)) { - char *astr = type_str(args); - char *pstr = type_str(params->type); - semantic_error(scope->fctx, args, - "%s does not implement %s", - astr, pstr); - free(astr); - free(pstr); - return -1; - } - - params = params->next; - args = args->next; - } - - if (args || params) { - semantic_error(scope->fctx, target, - "wrong number of type arguments"); - return -1; - } - - return 0; -} - static size_t member_count(struct ast_node *exists) { assert(exists->node_type == AST_STRUCT); @@ -1448,6 +1433,22 @@ static struct ast_node *lookup_struct_member(struct ast_node *struc, return lookup_struct_member_idx(struc, find, idx); } +static struct ast_node *lookup_enum_member(struct ast_node *enu, + struct ast_node *find) +{ + size_t i = 0; + struct ast_node *m = enu->_enum.body; + while (m) { + assert(m->node_type == AST_VAL); + if (identical_ast_nodes(0, find, m->_val.id)) + break; + m = m->next; + i++; + } + + return m; +} + static int init_struct(struct act_state *state, struct scope *scope, struct ast_node *exists, struct ast_node *init) { @@ -1529,7 +1530,7 @@ static int actualize_struct_init(struct act_state *state, return -1; } - struct ast_node *id = struct_type->_type.struc.struc; + struct ast_node *id = struct_type->_type.struc.id; struct ast_node *exists = file_scope_resolve_type(scope, id); assert(exists); @@ -1909,7 +1910,7 @@ static int actualize_struct(struct act_state *state, } /* could maybe be renamed, but essentially dot in copper works as either - * -> or . in C, so allow structures or templates and single lever pointers to + * -> or . in C, so allow structures or templates and single level pointers to * structures or templates. */ static int has_members(struct ast_node *type) { @@ -2004,6 +2005,86 @@ static int actualize_assign(struct act_state *state, struct scope *scope, return 0; } +static int actualize_fetch(struct act_state *state, struct scope *scope, + struct ast_node *fetch) +{ + assert(fetch->node_type == AST_FETCH); + struct ast_node *type = fetch->_fetch.type; + if (actualize(state, scope, type)) + return -1; + + if (type->_type.kind != AST_TYPE_ENUM) { + semantic_error(scope->fctx, type, "type is not an enum"); + return -1; + } + + struct ast_node *id = fetch->_fetch.id; + struct ast_node *enu = file_scope_resolve_type(scope, type->_type.id); + assert(enu); + + struct ast_node *member = lookup_enum_member(enu, id); + if (!member) { + char *estr = type_str(type); + semantic_error(scope->fctx, id, "no such member in enum %s"); + free(estr); + return -1; + } + + fetch->type = enu->type; + return 0; +} + +static int actualize_enum(struct act_state *state, struct scope *scope, + struct ast_node *node) +{ + assert(node->node_type == AST_ENUM); + struct ast_node *type = node->_enum.type; + struct scope *enum_scope = node->scope; + + /* TODO: here we could save space by choosing the smallest type that + * fits */ + if (!type) { + type = i64_type(); + node->_enum.type = type; + } else if (actualize(state, enum_scope, type)) + return -1; + + long long counter = 0; + node->type = type; + struct ast_node *members = node->_enum.body; + while (members) { + members->type = type; + if (members->_val.val) { + struct ast_node *val = members->_val.val; + if (actualize(state, enum_scope, val)) + return -1; + + if (val->node_type != AST_CONST) { + semantic_error(scope->fctx, members, + "unable to process nonconstant expression"); + return -1; + } + + if (val->_const.kind != AST_CONST_INTEGER) { + semantic_error(scope->fctx, members, + "not expandable to an integer constant"); + return -1; + } + + counter = val->_const.integer; + } + else { + members->_val.val = gen_int(counter); + } + + members = members->next; + counter++; + } + + /* TODO: check that we don't go outside the limits of the type */ + return 0; +} + static int actualize(struct act_state *state, struct scope *scope, struct ast_node *node) { @@ -2043,6 +2124,8 @@ static int actualize(struct act_state *state, struct scope *scope, case AST_DOT: ret |= actualize_dot(state, scope, node); break; case AST_INIT: ret |= actualize_init(state, scope, node); break; case AST_ASSIGN: ret |= actualize_assign(state, scope, node); break; + case AST_FETCH: ret |= actualize_fetch(state, scope, node); break; + case AST_ENUM: ret |= actualize_enum(state, scope, node); break; default: /* more like internal_error, maybe? */ @@ -310,6 +310,24 @@ void destroy_ctrl(struct ast_node *ctrl) free(ctrl); } +struct ast_node *gen_fetch(struct ast_node *id, struct ast_node *type) +{ + ALLOC_NODE(n, "fetch"); + n->node_type = AST_FETCH; + n->_fetch.id = id; + n->_fetch.type = type; + n->loc = id->loc; + return n; +} + +static void destroy_fetch(struct ast_node *fetch) +{ + assert(fetch->node_type == AST_FETCH); + destroy_ast_node(fetch->_fetch.id); + destroy_ast_node(fetch->_fetch.type); + free(fetch); +} + struct ast_node *gen_macro(struct ast_node *id, struct ast_node *params, struct ast_node *body) { @@ -437,16 +455,19 @@ struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *id, case AST_TYPE_UNION: n->_type.unio.id = id; - n->_type.unio.body = expr; - if (id) - n->loc = id->loc; - else - n->loc = expr->loc; + n->_type.unio.impls = expr; + n->loc = id->loc; break; case AST_TYPE_STRUCT: - n->_type.struc.struc = id; + n->_type.struc.id = id; + n->_type.struc.impls = expr; + n->loc = id->loc; + break; + + case AST_TYPE_ENUM: + n->_type.enu.id = id; n->_type.struc.impls = expr; n->loc = id->loc; break; @@ -503,13 +524,18 @@ void destroy_type(struct ast_node *type) break; case AST_TYPE_STRUCT: - destroy_ast_node(type->_type.struc.struc); + destroy_ast_node(type->_type.struc.id); DESTROY_LIST(type->_type.struc.impls); break; case AST_TYPE_UNION: - DESTROY_LIST(type->_type.unio.body); destroy_ast_node(type->_type.unio.id); + DESTROY_LIST(type->_type.unio.impls); + break; + + case AST_TYPE_ENUM: + destroy_ast_node(type->_type.enu.id); + destroy_ast_node(type->_type.enu.type); break; case AST_TYPE_SIGN: @@ -872,6 +898,7 @@ void destroy_ast_node(struct ast_node *node) assert(node->node_type); switch (node->node_type) { + case AST_FETCH: destroy_fetch(node); break; case AST_UNION: destroy_union(node); break; case AST_ASSIGN: destroy_assign(node); break; case AST_INIT: destroy_init(node); break; @@ -1028,6 +1055,17 @@ static void dump_flags(struct ast_node *node) static void __dump_ast(int depth, struct ast_node *node) { switch (node->node_type) { + case AST_FETCH: + dump(depth, "{FETCH:"); + dump_flags(node); + putchar('\n'); + + dump_ast(depth + 1, node->_fetch.id); + dump_ast(depth + 1, node->_fetch.type); + + dump(depth, "}\n"); + break; + case AST_UNION: dump(depth, "{UNION:"); dump_flags(node); @@ -1282,14 +1320,20 @@ static void __dump_ast(int depth, struct ast_node *node) printf(" STRUCT\n"); /* oh yeah, struc is at least right now just an ID that * we can use to fetch the actual struct with. */ - dump_ast(depth + 1, node->_type.struc.struc); + dump_ast(depth + 1, node->_type.struc.id); dump_ast(depth + 1, node->_type.struc.impls); break; + case AST_TYPE_ENUM: + printf(" ENUM\n"); + dump_ast(depth + 1, node->_type.enu.id); + dump_ast(depth + 1, node->_type.enu.type); + break; + case AST_TYPE_UNION: printf(" UNION\n"); dump_ast(depth + 1, node->_type.unio.id); - dump_ast(depth + 1, node->_type.unio.body); + dump_ast(depth + 1, node->_type.unio.impls); break; case AST_TYPE_SIGN: printf(" SIGN\n"); @@ -1500,6 +1544,11 @@ struct ast_node *clone_ast_node(struct ast_node *node) assert(node->node_type); struct ast_node *new = NULL; switch (node->node_type) { + case AST_FETCH: + new = gen_fetch(clone_ast_node(node->_fetch.id), + clone_ast_node(node->_fetch.type)); + break; + case AST_UNION: new = gen_union(clone_ast_node(node->_union.id), clone_ast_node(node->_union.generics), @@ -1632,15 +1681,22 @@ struct ast_node *clone_ast_node(struct ast_node *node) case AST_TYPE_STRUCT: new = gen_type(AST_TYPE_STRUCT, - clone_ast_node(node->_type.struc.struc), + clone_ast_node(node->_type.struc.id), clone_ast_node(node->_type.struc.impls), NULL); break; + case AST_TYPE_ENUM: + new = gen_type(AST_TYPE_ENUM, + clone_ast_node(node->_type.enu.id), + clone_ast_node(node->_type.enu.type), + NULL); + break; + case AST_TYPE_UNION: new = gen_type(AST_TYPE_UNION, clone_ast_node(node->_type.unio.id), - clone_ast_node(node->_type.unio.body), + clone_ast_node(node->_type.unio.impls), NULL); break; @@ -2083,8 +2139,7 @@ static int identical_type_sign(int exact, struct ast_node *a, static int identical_type_struct(int exact, struct ast_node *a, struct ast_node *b) { - if (!identical_ast_nodes(exact, a->_type.struc.struc, - b->_type.struc.struc)) + if (!identical_ast_nodes(exact, a->_type.struc.id, b->_type.struc.id)) return 0; if (!identical_ast_nodes(exact, a->_type.struc.impls, @@ -2100,7 +2155,20 @@ static int identical_type_union(int exact, struct ast_node *a, if (!identical_ast_nodes(exact, a->_type.unio.id, b->_type.unio.id)) return 0; - if (!identical_ast_nodes(exact, a->_type.unio.body, b->_type.unio.body)) + if (!identical_ast_nodes(exact, a->_type.unio.impls, + b->_type.unio.impls)) + return 0; + + return 1; +} + +static int identical_type_enum(int exact, struct ast_node *a, + struct ast_node *b) +{ + if (!identical_ast_nodes(exact, a->_type.enu.id, b->_type.enu.id)) + return 0; + + if (!identical_ast_nodes(exact, a->_type.enu.type, b->_type.enu.type)) return 0; return 1; @@ -2113,6 +2181,7 @@ static int identical_type(int exact, struct ast_node *a, struct ast_node *b) int ret = 0; switch (a->_type.kind) { + case AST_TYPE_ENUM: ret = identical_type_enum(exact, a, b); break; case AST_TYPE_ALIAS: ret = identical_type_alias(exact, a, b); break; case AST_TYPE_TEMPLATE: ret = identical_type_template(exact, a, b); break; @@ -2286,6 +2355,17 @@ static int identical_if(int exact, struct ast_node *a, struct ast_node *b) return 1; } +static int identical_fetch(int exact, struct ast_node *a, struct ast_node *b) +{ + if (!identical_ast_nodes(exact, a->_fetch.id, b->_fetch.id)) + return 0; + + if (!identical_ast_nodes(exact, a->_fetch.type, b->_fetch.type)) + return 0; + + return 1; +} + /* sort of unfortnate that we can't just do a direct memcmp... */ int identical_ast_nodes(int exact, struct ast_node *a, struct ast_node *b) { @@ -2318,6 +2398,7 @@ int identical_ast_nodes(int exact, struct ast_node *a, struct ast_node *b) int ret = 0; switch (a->node_type) { + case AST_FETCH: ret = identical_fetch(exact, a, b); break; case AST_UNION: ret = identical_union(exact, a, b); break; case AST_ASSIGN: ret = identical_assign(exact, a, b); break; case AST_INIT: ret = identical_init(exact, a, b); break; @@ -2598,7 +2679,7 @@ static int call_on_type_union(int (*call)(struct ast_node *, { int ret = 0; ret |= call(node->_type.unio.id, data); - ret |= call(node->_type.unio.body, data); + ret |= call(node->_type.unio.impls, data); return ret; } @@ -2606,7 +2687,7 @@ static int call_on_type_struct(int (*call)(struct ast_node *, void *), struct ast_node *node, void *data) { int ret = 0; - ret |= call(node->_type.struc.struc, data); + ret |= call(node->_type.struc.id, data); ret |= call(node->_type.struc.impls, data); return ret; } @@ -2639,11 +2720,21 @@ static int call_on_type_sign(int (*call)(struct ast_node *, return ret; } +static int call_on_type_enum(int (*call)(struct ast_node *, + void *), struct ast_node *node, void *data) +{ + int ret = 0; + ret |= call(node->_type.enu.id, data); + ret |= call(node->_type.enu.type, data); + return ret; +} + static int call_on_type(int (*call)(struct ast_node *, void *), struct ast_node *node, void *data) { int ret = 0; switch (node->_type.kind) { + case AST_TYPE_ENUM: ret = call_on_type_enum(call, node, data); break; case AST_TYPE_ALIAS: ret = call_on_type_alias(call, node, data); break; case AST_TYPE_TEMPLATE: ret = call_on_type_template(call, node, data); break; @@ -2726,6 +2817,15 @@ static int call_on_block(int (*call)(struct ast_node *, return call(node->_block.body, data); } +static int call_on_fetch(int (*call)(struct ast_node *, + void *), struct ast_node *node, void *data) +{ + int ret = 0; + ret |= call(node->_fetch.id, data); + ret |= call(node->_fetch.type, data); + return ret; +} + /* I guess this works, but it's not exactly optimal as the caller sort of has to * know when to continue to call on, and when it would cause an infinite loop. * I.e. a call on an ID that is forwarded results in an infinite loop. @@ -2741,6 +2841,7 @@ int ast_call_on(int (*call)(struct ast_node *, return ret; switch (node->node_type) { + case AST_FETCH: ret = call_on_fetch(call, node, data); break; case AST_UNION: ret = call_on_union(call, node, data); break; case AST_ASSIGN: ret = call_on_assign(call, node, data); break; case AST_INIT: ret = call_on_init(call, node, data); break; diff --git a/src/debug.c b/src/debug.c index 566da42..e42aedc 100644 --- a/src/debug.c +++ b/src/debug.c @@ -193,7 +193,7 @@ static void _type_str(FILE *fp, struct ast_node *type) } case AST_TYPE_STRUCT: { - struct ast_node *struc_id = type->_type.struc.struc; + struct ast_node *struc_id = type->_type.struc.id; fprintf(fp, "%s", struc_id->_id.id); struct ast_node *impls = type->_type.struc.impls; diff --git a/src/gen_lexer.h b/src/gen_lexer.h deleted file mode 100644 index 7fd7f5c..0000000 --- a/src/gen_lexer.h +++ /dev/null @@ -1,497 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ - -#ifndef yyHEADER_H -#define yyHEADER_H 1 -#define yyIN_HEADER 1 - -#line 6 "src/gen_lexer.h" - -#line 8 "src/gen_lexer.h" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 4 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include <inttypes.h> -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#ifndef SIZE_MAX -#define SIZE_MAX (~(size_t)0) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -/* begin standard C++ headers. */ - -/* TODO: this is always defined, so inline it */ -#define yyconst const - -#if defined(__GNUC__) && __GNUC__ >= 3 -#define yynoreturn __attribute__((__noreturn__)) -#else -#define yynoreturn -#endif - -/* An opaque pointer. */ -#ifndef YY_TYPEDEF_YY_SCANNER_T -#define YY_TYPEDEF_YY_SCANNER_T -typedef void* yyscan_t; -#endif - -/* For convenience, these vars (plus the bison vars far below) - are macros in the reentrant scanner. */ -#define yyin yyg->yyin_r -#define yyout yyg->yyout_r -#define yyextra yyg->yyextra_r -#define yyleng yyg->yyleng_r -#define yytext yyg->yytext_r -#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) -#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) -#define yy_flex_debug yyg->yy_flex_debug_r - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state -{ - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - int yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -}; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -void yyrestart ( FILE *input_file, yyscan_t yyscanner ); -void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer, yyscan_t yyscanner ); -YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size, yyscan_t yyscanner ); -void yy_delete_buffer ( YY_BUFFER_STATE b, yyscan_t yyscanner ); -void yy_flush_buffer ( YY_BUFFER_STATE b, yyscan_t yyscanner ); -void yypush_buffer_state ( YY_BUFFER_STATE new_buffer, yyscan_t yyscanner ); -void yypop_buffer_state ( yyscan_t yyscanner ); - -YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size, - yyscan_t yyscanner ); -YY_BUFFER_STATE yy_scan_string ( const char *yy_str, yyscan_t yyscanner ); -YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len, - yyscan_t yyscanner ); - -void *yyalloc ( yy_size_t, yyscan_t yyscanner ); -void *yyrealloc ( void *, yy_size_t, yyscan_t yyscanner ); -void yyfree ( void *, yyscan_t yyscanner ); - -/* Begin user sect3 */ - -#define yywrap(yyscanner) (/*CONSTCOND*/ 1) -#define YY_SKIP_YYWRAP - -#define yytext_ptr yytext_r - -#ifdef YY_HEADER_EXPORT_START_CONDITIONS -#define INITIAL 0 -#define SC_COMMENT 1 - -#endif - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include <unistd.h> -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -int yylex_init (yyscan_t* scanner); - -int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int yylex_destroy ( yyscan_t yyscanner ); - -int yyget_debug ( yyscan_t yyscanner ); - -void yyset_debug ( int debug_flag, yyscan_t yyscanner ); - -YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); - -void yyset_extra ( YY_EXTRA_TYPE user_defined, yyscan_t yyscanner ); - -FILE *yyget_in ( yyscan_t yyscanner ); - -void yyset_in ( FILE * _in_str, yyscan_t yyscanner ); - -FILE *yyget_out ( yyscan_t yyscanner ); - -void yyset_out ( FILE * _out_str, yyscan_t yyscanner ); - -int yyget_leng ( yyscan_t yyscanner ); - -char *yyget_text ( yyscan_t yyscanner ); - -int yyget_lineno ( yyscan_t yyscanner ); - -void yyset_lineno ( int _line_number, yyscan_t yyscanner ); - -int yyget_column ( yyscan_t yyscanner ); - -void yyset_column ( int _column_no, yyscan_t yyscanner ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap ( yyscan_t yyscanner ); -#else -extern int yywrap ( yyscan_t yyscanner ); -#endif -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy ( char *, const char *, int, yyscan_t yyscanner); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen ( const char *, yyscan_t yyscanner); -#endif - -#ifndef YY_NO_INPUT - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int yylex (yyscan_t yyscanner); - -#define YY_DECL int yylex (yyscan_t yyscanner) -#endif /* !YY_DECL */ - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - -#undef YY_NEW_FILE -#undef YY_FLUSH_BUFFER -#undef yy_set_bol -#undef yy_new_buffer -#undef yy_set_interactive -#undef YY_DO_BEFORE_ACTION - -#ifdef YY_DECL_IS_OURS -#undef YY_DECL_IS_OURS -#undef YY_DECL -#endif - -#ifndef yy_create_buffer_ALREADY_DEFINED -#undef yy_create_buffer -#endif -#ifndef yy_delete_buffer_ALREADY_DEFINED -#undef yy_delete_buffer -#endif -#ifndef yy_scan_buffer_ALREADY_DEFINED -#undef yy_scan_buffer -#endif -#ifndef yy_scan_string_ALREADY_DEFINED -#undef yy_scan_string -#endif -#ifndef yy_scan_bytes_ALREADY_DEFINED -#undef yy_scan_bytes -#endif -#ifndef yy_init_buffer_ALREADY_DEFINED -#undef yy_init_buffer -#endif -#ifndef yy_flush_buffer_ALREADY_DEFINED -#undef yy_flush_buffer -#endif -#ifndef yy_load_buffer_state_ALREADY_DEFINED -#undef yy_load_buffer_state -#endif -#ifndef yy_switch_to_buffer_ALREADY_DEFINED -#undef yy_switch_to_buffer -#endif -#ifndef yypush_buffer_state_ALREADY_DEFINED -#undef yypush_buffer_state -#endif -#ifndef yypop_buffer_state_ALREADY_DEFINED -#undef yypop_buffer_state -#endif -#ifndef yyensure_buffer_stack_ALREADY_DEFINED -#undef yyensure_buffer_stack -#endif -#ifndef yylex_ALREADY_DEFINED -#undef yylex -#endif -#ifndef yyrestart_ALREADY_DEFINED -#undef yyrestart -#endif -#ifndef yylex_init_ALREADY_DEFINED -#undef yylex_init -#endif -#ifndef yylex_init_extra_ALREADY_DEFINED -#undef yylex_init_extra -#endif -#ifndef yylex_destroy_ALREADY_DEFINED -#undef yylex_destroy -#endif -#ifndef yyget_debug_ALREADY_DEFINED -#undef yyget_debug -#endif -#ifndef yyset_debug_ALREADY_DEFINED -#undef yyset_debug -#endif -#ifndef yyget_extra_ALREADY_DEFINED -#undef yyget_extra -#endif -#ifndef yyset_extra_ALREADY_DEFINED -#undef yyset_extra -#endif -#ifndef yyget_in_ALREADY_DEFINED -#undef yyget_in -#endif -#ifndef yyset_in_ALREADY_DEFINED -#undef yyset_in -#endif -#ifndef yyget_out_ALREADY_DEFINED -#undef yyget_out -#endif -#ifndef yyset_out_ALREADY_DEFINED -#undef yyset_out -#endif -#ifndef yyget_leng_ALREADY_DEFINED -#undef yyget_leng -#endif -#ifndef yyget_text_ALREADY_DEFINED -#undef yyget_text -#endif -#ifndef yyget_lineno_ALREADY_DEFINED -#undef yyget_lineno -#endif -#ifndef yyset_lineno_ALREADY_DEFINED -#undef yyset_lineno -#endif -#ifndef yyget_column_ALREADY_DEFINED -#undef yyget_column -#endif -#ifndef yyset_column_ALREADY_DEFINED -#undef yyset_column -#endif -#ifndef yywrap_ALREADY_DEFINED -#undef yywrap -#endif -#ifndef yyget_lval_ALREADY_DEFINED -#undef yyget_lval -#endif -#ifndef yyset_lval_ALREADY_DEFINED -#undef yyset_lval -#endif -#ifndef yyget_lloc_ALREADY_DEFINED -#undef yyget_lloc -#endif -#ifndef yyset_lloc_ALREADY_DEFINED -#undef yyset_lloc -#endif -#ifndef yyalloc_ALREADY_DEFINED -#undef yyalloc -#endif -#ifndef yyrealloc_ALREADY_DEFINED -#undef yyrealloc -#endif -#ifndef yyfree_ALREADY_DEFINED -#undef yyfree -#endif -#ifndef yytext_ALREADY_DEFINED -#undef yytext -#endif -#ifndef yyleng_ALREADY_DEFINED -#undef yyleng -#endif -#ifndef yyin_ALREADY_DEFINED -#undef yyin -#endif -#ifndef yyout_ALREADY_DEFINED -#undef yyout -#endif -#ifndef yy_flex_debug_ALREADY_DEFINED -#undef yy_flex_debug -#endif -#ifndef yylineno_ALREADY_DEFINED -#undef yylineno -#endif -#ifndef yytables_fload_ALREADY_DEFINED -#undef yytables_fload -#endif -#ifndef yytables_destroy_ALREADY_DEFINED -#undef yytables_destroy -#endif -#ifndef yyTABLES_NAME_ALREADY_DEFINED -#undef yyTABLES_NAME -#endif - -#line 212 "src/lexer.l" - - -#line 492 "src/gen_lexer.h" -#undef yyIN_HEADER -#endif /* yyHEADER_H */ diff --git a/src/lexer.l b/src/lexer.l index e7dad6a..ce0b269 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -60,6 +60,7 @@ STRING \"(\\.|[^"\\])*\" \n {} } +"::" {return SCOPE;} "(" {return LPAREN;} ")" {return RPAREN;} "{" {return LBRACE;} diff --git a/src/parser.y b/src/parser.y index 665a6a0..4ad4d8b 100644 --- a/src/parser.y +++ b/src/parser.y @@ -108,6 +108,7 @@ %token RBRACKET "]" %token AS "as" %token DOT "." +%token SCOPE "::" %token FATARROW "=>" /* precedence */ @@ -127,6 +128,7 @@ %left "as" "sizeof" "typeof" %right "'" "!" "~" %left "." "=>" "(" ")" +%left "::" /* why doesn't bison allow <*> for %nterm? would be so much easier */ %nterm <node> import binary_op unary_op arg arg_list decl_list call expr @@ -252,6 +254,7 @@ expr: id { $$ = $1; } | "(" var_init ")" { $$ = $2; } | "sizeof" expr { $$ = gen_sizeof($2); } | expr "as" type { $$ = gen_cast($1, $3); } + | id "::" type { $$ = gen_fetch($1, $3); } | "as" type { $$ = gen_as($2); } | embed { $$ = $1; } | lambda { $$ = $1; } @@ -553,7 +556,7 @@ type_template: "type" id "{" template_list "}" { } ; -enum_val: id { $$ = gen_val($1, gen_int(0)); } +enum_val: id { $$ = gen_val($1, NULL); } | id "=" expr { $$ = gen_val($1, $3); } ; diff --git a/src/source.mk b/src/source.mk index 5b3d2ae..4f707de 100644 --- a/src/source.mk +++ b/src/source.mk @@ -5,6 +5,6 @@ gen/gen_parser.c: src/parser.y bison -Wcounterexamples -H -o $@ $< gen/gen_lexer.c: src/lexer.l - flex --header-file=src/gen_lexer.h -o $@ $< + flex --header-file=gen/gen_lexer.h -o $@ $< include/cu/parser.h: gen/gen_lexer.c gen/gen_parser.c |
