From f6c07d86d0618f2ac43474f47fbf1f0082ecefc6 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 13 Sep 2019 00:38:52 +0200 Subject: [PATCH] CT for now parses properly. --- README.md | 4 +-- resources/c3.l | 10 ++++++- resources/grammar.y | 12 ++++++--- src/compiler/ast.c | 12 +++++++++ src/compiler/codegen.c | 26 +++++++----------- src/compiler/compiler_internal.h | 10 +++++++ src/compiler/enums.h | 4 ++- src/compiler/parser.c | 45 ++++++++++++++++++++++++++------ src/compiler/tokens.c | 10 ++++--- 9 files changed, 96 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index da75afbf9..7235cb5d9 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,7 @@ There are some small work being done on the parser here, but most of the structu #### What's missing in the parser - `asm` sections. -- `$each` compile time statement. - Macro parameter lists to imports. -- extending `generics` declaration. - auxiliary data for enums. #### What's missing in the semantic analyser @@ -37,7 +35,7 @@ There are some small work being done on the parser here, but most of the structu - `catch`, `throws` and `try` statements. - `generic` not analysed. - `attribute` not analysed. -- `$switch` and `$each` not handled. +- `$switch` and `$for` not handled. - Enums not correctly handled. - Errors not correctly handles. - Type resolution not complete for all types. diff --git a/resources/c3.l b/resources/c3.l index 60be33b08..f9810f56b 100644 --- a/resources/c3.l +++ b/resources/c3.l @@ -62,7 +62,15 @@ void comment(void); "throws" { count(); return(THROWS); } "func" { count(); return(FUNC); } "nil" { count(); return(NIL); } -"next" { count(); return(NEXT); +"next" { count(); return(NEXT); } +"in" { count(); return(IN); } +"$for" { count(); return(CTFOR); } +"$case" { count(); return(CTCASE); } +"$switch" { count(); return(CTSWITCH); } +"$default" { count(); return(CTDEFAULT); } +"$if" { count(); return(CTIF); } +"$elif" { count(); return(CTELIF); } +"$else" { count(); return(CTELSE); } [_]*[A-Z]{UA}* { count(); return(CONST_IDENT); } [_]*[A-Z]{UA}*[a-z]{AN}* { count(); return(TYPE_IDENT); } diff --git a/resources/grammar.y b/resources/grammar.y index 98ccee200..7ed4cf47e 100644 --- a/resources/grammar.y +++ b/resources/grammar.y @@ -21,8 +21,8 @@ void yyerror(char *s); %token STRUCT UNION ENUM ELLIPSIS AS LOCAL %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN -%token TYPE FUNC ERROR MACRO GENERIC CTIF CTELIF CTENDIF CTELSE CTSWITCH CTCASE CTDEFAULT CTEACH -%token THROWS THROW TRY CATCH SCOPE PUBLIC DEFER ATTRIBUTE +%token TYPE FUNC ERROR MACRO GENERIC CTIF CTELIF CTENDIF CTELSE CTSWITCH CTCASE CTDEFAULT CTFOR +%token THROWS THROW TRY CATCH SCOPE PUBLIC DEFER ATTRIBUTE IN %start translation_unit %% @@ -32,6 +32,7 @@ path | path IDENT SCOPE ; + ident_expression : CONST_IDENT | IDENT @@ -298,11 +299,16 @@ ct_switch_body | ct_switch_body ct_case_statement ; +ct_for_stmt + : CTFOR '(' CT_IDENT IN expression ')' statement + | CTFOR '(' CT_IDENT ',' CT_IDENT IN expression ')' statement + ; + ct_statement : ct_if compound_statement | ct_if compound_statement ct_else_body | ct_switch '{' ct_switch_body '}' - | CTEACH '(' expression AS CT_IDENT ')' statement + | ct_for_stmt ; throw_statement diff --git a/src/compiler/ast.c b/src/compiler/ast.c index ce8e42981..e98544ad9 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -583,6 +583,18 @@ static void fprint_ast_recursive(FILE *file, Ast *ast, int indent) fprint_ast_recursive(file, ast->while_stmt.cond, indent + 1); fprint_ast_recursive(file, ast->while_stmt.body, indent + 1); break; + case AST_CT_FOR_STMT: + if (ast->ct_for_stmt.index.string) + { + fprintf(file, "($for %s, %s\n", ast->ct_for_stmt.index.string, ast->ct_for_stmt.value.string); + } + else + { + fprintf(file, "($for %s\n", ast->ct_for_stmt.value.string); + } + fprint_expr_recursive(file, ast->ct_for_stmt.expr, indent + 1); + fprint_ast_recursive(file, ast->ct_for_stmt.body, indent + 1); + break; case AST_DO_STMT: fprintf(file, "(do\n"); fprint_ast_recursive(file, ast->do_stmt.body, indent + 1); diff --git a/src/compiler/codegen.c b/src/compiler/codegen.c index e80050c13..92a808db9 100644 --- a/src/compiler/codegen.c +++ b/src/compiler/codegen.c @@ -680,8 +680,6 @@ static void codegen_ast(Context *context, Ast *ast, int indent) UNREACHABLE case AST_ASM_STMT: break; - case AST_ATTRIBUTE: - break; case AST_BREAK_STMT: codegen_emit_break_stmt(context, ast, indent); return; @@ -696,12 +694,6 @@ static void codegen_ast(Context *context, Ast *ast, int indent) break; case AST_CONTINUE_STMT: break; - case AST_CT_IF_STMT: - break; - case AST_CT_ELIF_STMT: - break; - case AST_CT_ELSE_STMT: - break; case AST_DECLARE_STMT: codegen_declare_stmt(context, ast, indent); return; @@ -756,21 +748,21 @@ static void codegen_ast(Context *context, Ast *ast, int indent) return; case AST_VOLATILE_STMT: break; - case AST_WHILE_STMT: - UNREACHABLE - case AST_GENERIC_CASE_STMT: - break; - case AST_GENERIC_DEFAULT_STMT: - break; case AST_STMT_LIST: codegen_emit_stmt_list(context, ast, indent); return; case AST_CT_SWITCH_STMT: - break; case AST_CT_DEFAULT_STMT: - break; + case AST_CT_IF_STMT: + case AST_CT_ELIF_STMT: + case AST_CT_ELSE_STMT: case AST_CT_CASE_STMT: - break; + case AST_ATTRIBUTE: + case AST_CT_FOR_STMT: + case AST_GENERIC_CASE_STMT: + case AST_GENERIC_DEFAULT_STMT: + case AST_WHILE_STMT: + UNREACHABLE } TODO } diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 4dfa9d824..ddae5ac4e 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -229,6 +229,7 @@ typedef struct struct _Ast **cases; Token *parameters; Type *rtype; // May be null! + Path *path; // For redefinition } GenericDecl; @@ -543,6 +544,14 @@ typedef struct Ast *body; } AstCtCaseStmt; +typedef struct +{ + Token index; + Token value; + Expr *expr; + Ast *body; +} AstCtForStmt; + typedef struct _Ast { AstKind ast_kind : 8; @@ -577,6 +586,7 @@ typedef struct _Ast AstCtIfStmt ct_if_stmt; AstCtIfStmt ct_elif_stmt; Ast *ct_else_stmt; + AstCtForStmt ct_for_stmt; AstGenericCaseStmt generic_case_stmt; Ast *generic_default_stmt; Ast** stmt_list; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index d063f7a6e..5bda5ca7f 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -36,6 +36,7 @@ typedef enum AST_CT_IF_STMT, AST_CT_ELIF_STMT, AST_CT_ELSE_STMT, + AST_CT_FOR_STMT, AST_CT_SWITCH_STMT, AST_CT_DEFAULT_STMT, AST_CT_CASE_STMT, @@ -395,6 +396,7 @@ typedef enum TOKEN_GOTO, TOKEN_IF, TOKEN_IMPORT, + TOKEN_IN, TOKEN_LOCAL, TOKEN_MACRO, TOKEN_MODULE, @@ -428,7 +430,7 @@ typedef enum TOKEN_CT_CASE, // $case TOKEN_CT_DEFAULT, // $default - TOKEN_CT_EACH, // $each + TOKEN_CT_FOR, // $for TOKEN_CT_ELIF, // $elif TOKEN_CT_ELSE, // $else TOKEN_CT_IF, // $if diff --git a/src/compiler/parser.c b/src/compiler/parser.c index c2395b691..1c3e6da30 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -1025,10 +1025,32 @@ static inline Ast* parse_ct_if_stmt(void) } -static inline Ast* parse_ct_each_stmt(void) +/** + * ct_for_stmt + * : CTFOR '(' CT_IDENT IN expression ')' statement + * | CTFOR '(' CT_IDENT, CT_IDENT IN expression ')' statement + * ; + * + * @return + */ +static inline Ast* parse_ct_for_stmt(void) { - - TODO + Ast *ast = AST_NEW(AST_CT_FOR_STMT, tok); + advance_and_verify(TOKEN_CT_FOR); + CONSUME_OR(TOKEN_LPAREN, &poisoned_ast); + if (next_tok.type == TOKEN_COMMA) + { + ast->ct_for_stmt.index = tok; + TRY_CONSUME_OR(TOKEN_CT_IDENT, "Expected a compile time index variable", &poisoned_ast); + advance_and_verify(TOKEN_COMMA); + } + ast->ct_for_stmt.value = tok; + TRY_CONSUME_OR(TOKEN_CT_IDENT, "Expected a compile time variable", &poisoned_ast); + TRY_CONSUME_OR(TOKEN_IN, "Expected 'in'.", &poisoned_ast); + ast->ct_for_stmt.expr = TRY_EXPR_OR(parse_expr(), &poisoned_ast); + CONSUME_OR(TOKEN_RPAREN, &poisoned_ast); + ast->ct_for_stmt.body = TRY_AST(parse_stmt()); + return ast; } @@ -1312,8 +1334,8 @@ static Ast *parse_stmt(void) return parse_ct_if_stmt(); case TOKEN_CT_SWITCH: return parse_ct_switch_stmt(); - case TOKEN_CT_EACH: - return parse_ct_each_stmt(); + case TOKEN_CT_FOR: + return parse_ct_for_stmt(); case TOKEN_THROW: return parse_throw_stmt(); case TOKEN_VOLATILE: @@ -1416,6 +1438,7 @@ static Ast *parse_stmt(void) case TOKEN_CT_ELIF: case TOKEN_CT_ELSE: case TOKEN_CT_DEFAULT: + case TOKEN_IN: SEMA_ERROR(tok, "Unexpected '%s' found when expecting a statement.", token_type_to_string(tok.type)); advance(); return &poisoned_ast; @@ -1913,10 +1936,14 @@ static inline Ast *parse_generics_statements(void) /** - * // TODO module? * generics_declaration - * : GENERIC IDENT '(' macro_argument_list ')' '{' generics_body '}' - * | GENERIC type_expression IDENT '(' macro_argument_list ')' '{' generics_body '}' + * : GENERIC opt_path IDENT '(' macro_argument_list ')' '{' generics_body '}' + * | GENERIC type_expression opt_path IDENT '(' macro_argument_list ')' '{' generics_body '}' + * ; + * + * opt_path + * : + * | path * ; * * @param visibility @@ -1930,7 +1957,9 @@ static inline Decl *parse_generics_declaration(Visibility visibility) { rtype = TRY_TYPE_OR(parse_type_expression(), &poisoned_decl); } + Path *path = parse_path(); Decl *decl = decl_new_user_defined_type(tok, DECL_GENERIC, visibility); + decl->generic_decl.path = path; if (!consume_ident("generic function name")) return &poisoned_decl; decl->generic_decl.rtype = rtype; Token *parameters = NULL; diff --git a/src/compiler/tokens.c b/src/compiler/tokens.c index 974297c24..baf29cbec 100644 --- a/src/compiler/tokens.c +++ b/src/compiler/tokens.c @@ -191,10 +191,12 @@ const char *token_type_to_string(TokenType type) return "generic"; case TOKEN_GOTO: return "goto"; - case TOKEN_IMPORT: - return "import"; case TOKEN_IF: return "if"; + case TOKEN_IMPORT: + return "import"; + case TOKEN_IN: + return "in"; case TOKEN_LOCAL: return "local"; case TOKEN_MACRO: @@ -321,8 +323,8 @@ const char *token_type_to_string(TokenType type) return "$case"; case TOKEN_CT_DEFAULT: return "$default"; - case TOKEN_CT_EACH: - return "$each"; + case TOKEN_CT_FOR: + return "$for"; case TOKEN_CT_ELSE: return "$else"; case TOKEN_CT_ELIF: