mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
CT for now parses properly.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user