diff --git a/v0/parser.c b/v0/parser.c index 089c692..d10c58e 100644 --- a/v0/parser.c +++ b/v0/parser.c @@ -72,6 +72,52 @@ Module* parser_parse(TokenStream* ts) { } } + // Now t holds the first non-import token. If it's not TOKEN_ALIAS, return. + // If it is, process it. + while (t.token == TOKEN_ALIAS) { + AliasDeclaration* new_aliases = realloc(module->aliases, (module->alias_count + 1) * sizeof(AliasDeclaration)); + if (!new_aliases) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + module->aliases = new_aliases; + + t = tokenstream_next(ts); + if (t.token != TOKEN_IDENTIFIER) { + log_on_line(&t.location, t.location.column_end, "expected alias name"); + parser_free(module); + return NULL; + } + AliasDeclaration alias; + alias.name = t; + + t = tokenstream_next(ts); + if (t.token != TOKEN_ASSIGN) { + log_on_line(&t.location, t.location.column_end, "expected '='"); + parser_free(module); + return NULL; + } + + t = tokenstream_next(ts); + if (t.token != TOKEN_IDENTIFIER || strncmp(t.text.data, "int32", t.text.length) != 0) { + log_on_line(&t.location, t.location.column_end, "expected type"); + parser_free(module); + return NULL; + } + alias.value = (TypeExpression){ .tag = TYPE_EXPRESSION_BUILTIN, .builtin = { .bitSize = 32, .isSigned = true } }; + + module->aliases[module->alias_count] = alias; + module->alias_count++; + + t = tokenstream_next(ts); + if (t.token != TOKEN_SEMICOLON) { + log_on_line(&t.location, t.location.column_end, "expected ';'"); + parser_free(module); + return NULL; + } + t = tokenstream_next(ts); + } + return module; } diff --git a/v0/test.c b/v0/test.c index 63a2457..084d10a 100644 --- a/v0/test.c +++ b/v0/test.c @@ -194,6 +194,7 @@ static TestCase s_tests[] = { {"parser_bad_import_name", test_parser_bad_import_name}, {"parser_imports", test_parser_imports}, {"parser_public_imports", test_parser_public_imports}, + {"parser_alias_simple", test_parser_alias_simple}, {"log_error", test_log_error}, {"log_on_line", test_log_on_line}, {"log_on_line_variadic", test_log_on_line_variadic}, diff --git a/v0/test_parser.c b/v0/test_parser.c index dbb2e97..75c8a46 100644 --- a/v0/test_parser.c +++ b/v0/test_parser.c @@ -82,3 +82,14 @@ static void test_parser_public_imports(void) { parser_free(m); tokenstream_close(ts); } + +static void test_parser_alias_simple(void) { + Module* m = test_get_ast(); + + assert_int(1, m->alias_count, "expected correct number of aliases"); + AliasDeclaration alias = m->aliases[0]; + assert_string("myalias", alias.name.text, "expected correct alias name"); + assert_int(TYPE_EXPRESSION_BUILTIN, alias.value.tag, "expected correct alias tag"); + assert_int(32, alias.value.builtin.bitSize, "expected bitSize 32"); + assert_true(alias.value.builtin.isSigned, "expected signed"); +} diff --git a/v0/tests/parser_alias_simple.c2 b/v0/tests/parser_alias_simple.c2 new file mode 100644 index 0000000..8e40d71 --- /dev/null +++ b/v0/tests/parser_alias_simple.c2 @@ -0,0 +1,3 @@ +module mymodule; + +alias myalias = int32; diff --git a/v0/token.c b/v0/token.c index cc0307f..f65c3e4 100644 --- a/v0/token.c +++ b/v0/token.c @@ -30,6 +30,7 @@ typedef struct { static const KeywordMap keywords[] = { {"module", TOKEN_MODULE}, {"import", TOKEN_IMPORT}, + {"alias", TOKEN_ALIAS}, {"void", TOKEN_VOID}, }; @@ -220,6 +221,7 @@ Token tokenstream_next(TokenStream* ts) { case ']': return create_token(ts, TOKEN_BRACKET_CLOSE, start_text, 1, start_line, start_column, line_start); case ',': return create_token(ts, TOKEN_COMMA, start_text, 1, start_line, start_column, line_start); case ';': return create_token(ts, TOKEN_SEMICOLON, start_text, 1, start_line, start_column, line_start); + case '=': return create_token(ts, TOKEN_ASSIGN, start_text, 1, start_line, start_column, line_start); } /* Keywords and identifiers */ diff --git a/v0/token.h b/v0/token.h index 741c128..679d376 100644 --- a/v0/token.h +++ b/v0/token.h @@ -14,6 +14,7 @@ typedef enum { TOKEN_MODULE, TOKEN_IMPORT, TOKEN_SEMICOLON, + TOKEN_ALIAS, /* Symbols */ TOKEN_PARENT_OPEN, @@ -21,9 +22,11 @@ typedef enum { TOKEN_BRACKET_OPEN, TOKEN_BRACKET_CLOSE, TOKEN_COMMA, + TOKEN_ASSIGN, /* Primitives */ TOKEN_VOID, + TOKEN_BUILTIN_TYPE, /* Variable */ TOKEN_IDENTIFIER,