AST idea
This commit is contained in:
169
new_parse.c
169
new_parse.c
@@ -31,7 +31,7 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
|
||||
|
||||
// @Note(Krzosa): Print nice error message
|
||||
{
|
||||
printf("Error: %s %s:%d\n", string.str, token->file.str, (S32)token->line);
|
||||
printf("\nError: %s %s:%d\n", string.str, token->file.str, (S32)token->line);
|
||||
|
||||
// @Note(Krzosa): Print error line
|
||||
{
|
||||
@@ -171,7 +171,6 @@ Compound literals
|
||||
- { }
|
||||
|
||||
*/
|
||||
|
||||
function Expr_Compound_Field *
|
||||
parse_expr_compound_field(Parser *p){
|
||||
Token *token = token_get(p);
|
||||
@@ -554,7 +553,6 @@ name::const = 4254;
|
||||
// data: [24]U32;
|
||||
// }
|
||||
// }
|
||||
|
||||
*/
|
||||
function void
|
||||
parse_note_list(Parser *p, Note *parent) {
|
||||
@@ -602,34 +600,37 @@ parse_assign_expr(Parser *p){
|
||||
}
|
||||
|
||||
function Typespec *
|
||||
parse_optional_type(Parser *p){
|
||||
parse_optional_type(Parser *p, Intern_String type){
|
||||
Typespec *result = 0;
|
||||
if(token_match(p, TK_Colon)){
|
||||
result = parse_typespec(p);
|
||||
}
|
||||
else{
|
||||
result = typespec_name(p->arena, token_get(p), intern_int);
|
||||
result = typespec_name(p->arena, token_get(p), type);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_enum(Parser *p, Token *name){
|
||||
Typespec *typespec = parse_optional_type(p);
|
||||
Typespec *typespec = parse_optional_type(p, intern_int);
|
||||
Decl *result = decl_enum(p->arena, name, name->intern_val, typespec);
|
||||
token_expect(p, TK_OpenBrace);
|
||||
do{
|
||||
do {
|
||||
Note notes = parse_notes(p);
|
||||
Token *val = token_expect(p, TK_Identifier);
|
||||
Expr *expr = parse_assign_expr(p);
|
||||
decl_enum_push(p->arena, result, val, val->intern_val, expr, ¬es);
|
||||
} while(token_match(p, TK_Comma));
|
||||
if(!token_match(p, TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}while(!token_is(p, TK_CloseBrace));
|
||||
token_expect(p, TK_CloseBrace);
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
parse_var_decl(Parser *p, Decl *parent, Token *name){
|
||||
parse_var_decl(Parser *p, Decl *parent, Token *name, Note *notes){
|
||||
Token *name_stack[64];
|
||||
S64 name_stack_len = 0;
|
||||
name_stack[name_stack_len++] = name;
|
||||
@@ -640,6 +641,7 @@ parse_var_decl(Parser *p, Decl *parent, Token *name){
|
||||
token_expect(p, TK_Semicolon);
|
||||
for(S64 i = 0; i < name_stack_len; i++){
|
||||
Decl *decl = decl_variable(p->arena, name_stack[i], name_stack[i]->intern_val, typespec, 0);
|
||||
decl_pass_notes(decl, notes);
|
||||
decl_struct_push(parent, decl);
|
||||
}
|
||||
}
|
||||
@@ -651,35 +653,38 @@ parse_struct(Parser *p, Token *name, Decl_Kind struct_kind){
|
||||
Decl *result = decl_struct(p->arena, struct_kind, token, intern_name);
|
||||
token_expect(p, TK_OpenBrace);
|
||||
do {
|
||||
Note notes = parse_notes(p);
|
||||
Token *token = token_get(p);
|
||||
if(token_match_keyword(p, keyword_union)){
|
||||
Decl *decl = parse_struct(p, 0, DECL_SubUnion);
|
||||
decl_pass_notes(decl, ¬es);
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_struct)){
|
||||
Decl *decl = parse_struct(p, 0, DECL_SubStruct);
|
||||
decl_pass_notes(decl, ¬es);
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
else if(token_match(p, TK_Identifier)){
|
||||
if(token_is(p, TK_Colon)){
|
||||
if(token_peek_is_keyword(p, keyword_union, 1)){
|
||||
token_next(p);
|
||||
token_next(p);
|
||||
token_next(p); token_next(p);
|
||||
Decl *decl = parse_struct(p, token, DECL_SubUnion);
|
||||
decl_pass_notes(decl, ¬es);
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
else if(token_peek_is_keyword(p, keyword_struct, 1)){
|
||||
token_next(p);
|
||||
token_next(p);
|
||||
token_next(p); token_next(p);
|
||||
Decl *decl = parse_struct(p, token, DECL_SubStruct);
|
||||
decl_pass_notes(decl, ¬es);
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
else{
|
||||
parse_var_decl(p, result, token);
|
||||
parse_var_decl(p, result, token, ¬es);
|
||||
}
|
||||
}
|
||||
else{
|
||||
parse_var_decl(p, result, token);
|
||||
parse_var_decl(p, result, token, ¬es);
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -690,9 +695,47 @@ parse_struct(Parser *p, Token *name, Decl_Kind struct_kind){
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_decl(Parser *p){
|
||||
Decl *result = 0;
|
||||
parse_typedef(Parser *p, Token *name){
|
||||
token_expect(p, TK_Assign);
|
||||
Typespec *typespec = parse_typespec(p);
|
||||
token_expect(p, TK_Semicolon);
|
||||
Decl *result = decl_typedef(p->arena, name, name->intern_val, typespec);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_const(Parser *p, Token *name){
|
||||
Typespec *typespec = 0;
|
||||
if(token_match(p, TK_Colon))
|
||||
typespec = parse_typespec(p);
|
||||
token_expect(p, TK_Assign);
|
||||
Expr *expr = parse_expr(p);
|
||||
token_expect(p, TK_Semicolon);
|
||||
Decl *result = decl_const(p->arena, name, name->intern_val, expr, typespec);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_function(Parser *p, Token *name){
|
||||
Decl *result = decl_function(p->arena, name, name->intern_val, 0);
|
||||
if(!token_is(p, TK_CloseParen)){
|
||||
do{
|
||||
name = token_expect(p, TK_Identifier);
|
||||
token_expect(p, TK_Colon);
|
||||
Typespec *typespec = parse_typespec(p);
|
||||
decl_func_push(p->arena, result, name, name->intern_val, typespec);
|
||||
} while(token_match(p, TK_Comma));
|
||||
}
|
||||
token_expect(p, TK_CloseParen);
|
||||
result->func_decl.ret = parse_optional_type(p, intern_void);
|
||||
token_expect(p, TK_Semicolon);
|
||||
return result;
|
||||
}
|
||||
|
||||
function B32
|
||||
parse_decl(Parser *p, Decl *parent){
|
||||
Token *name = 0;
|
||||
Decl *result = 0;
|
||||
Note note = parse_notes(p);
|
||||
if((name = token_match(p, TK_Identifier))){
|
||||
if(token_match(p, TK_DoubleColon)){
|
||||
@@ -706,31 +749,91 @@ parse_decl(Parser *p){
|
||||
else if((token = token_match_keyword(p, keyword_struct))){
|
||||
result = parse_struct(p, name, DECL_Struct);
|
||||
}
|
||||
else if((token = token_match_keyword(p, keyword_typedef))){
|
||||
result = parse_typedef(p, name);
|
||||
}
|
||||
else if((token = token_match_keyword(p, keyword_const))){
|
||||
// Const value
|
||||
result = parse_const(p, name);
|
||||
}
|
||||
else if((token = token_match(p, TK_OpenParen))){
|
||||
// Function
|
||||
result = parse_function(p, name);
|
||||
}
|
||||
else{
|
||||
parser_push_error(p, token_get(p), "Expected token of kind todo:decl_tokens");
|
||||
token = token_get(p);
|
||||
parser_push_error(p, token, "Expected a declaration keyword. Got instead: %s", token_kind_string[token->kind]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
parser_push_error(p, token_get(p), "Expected token of kind '::'");
|
||||
Token *token = token_get(p);
|
||||
parser_push_error(p, token, "Expected a declaration which starts with token '::' got instead"
|
||||
"token '%s'", token_kind_string[token->kind]);
|
||||
}
|
||||
}
|
||||
|
||||
if(result){
|
||||
decl_pass_notes(result, ¬e);
|
||||
decl_list_push(parent, result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function Decl
|
||||
parse_decls(Parser *p){
|
||||
Decl decl_list = {.kind=DECL_List};
|
||||
while(!token_is(p, TK_End)){
|
||||
B32 success = parse_decl(p, &decl_list);
|
||||
if(!success){
|
||||
parser_push_error(p, token_get(p), "Failed to parse decls, unexpected token!");
|
||||
}
|
||||
}
|
||||
return decl_list;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Statement parsing
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
stmt_list = '{' stmt* '}'
|
||||
stmt =
|
||||
| stmt_list
|
||||
| 'return' expr ';'
|
||||
| 'if' expr stmt_list
|
||||
| 'for' simple_stmt_list ';' expr ';' simple_stmt_list stmt_list
|
||||
| 'for' expr stmt_list
|
||||
| expr assign? ';'
|
||||
//| 'while' expr stmt_or_stmt_list
|
||||
|
||||
*/
|
||||
|
||||
function Stmt *
|
||||
parse_stmt(Parser *p){
|
||||
Note notes = parse_notes(p);
|
||||
Stmt *result = 0;
|
||||
if(token_match_keyword(p, keyword_if)){
|
||||
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_for)){
|
||||
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_while)){
|
||||
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_return)){
|
||||
|
||||
}
|
||||
else if(token_match(p, TK_OpenBrace)){
|
||||
// Scope
|
||||
}
|
||||
else{
|
||||
// Expr
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Test code
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function S64
|
||||
eval_expr(Expr *expr){
|
||||
switch(expr->kind){
|
||||
@@ -875,15 +978,27 @@ parse_test_decls(){
|
||||
};
|
||||
for(SizeU i = 0; i < buff_cap(decls); i++){
|
||||
parser_restream(&p, decls[i], lit("Decl_Test"));
|
||||
Decl *decl = parse_decl(&p);
|
||||
assert(decl);
|
||||
decl_print(decl);
|
||||
Decl decl = parse_decls(&p);
|
||||
assert(decl.list_decl.first);
|
||||
decl_print(decl.list_decl.first);
|
||||
}
|
||||
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
function void
|
||||
parse_test_from_file(){
|
||||
const String FILENAME = lit("test.cc");
|
||||
Arena *scratch = arena_begin_scratch();
|
||||
String file = os_read_file(scratch, FILENAME);
|
||||
Parser p = parser_make_stream(scratch, file, FILENAME);
|
||||
Decl d = parse_decls(&p);
|
||||
decl_print(&d);
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
function void
|
||||
parse_test(){
|
||||
parse_test_expr();
|
||||
parse_test_decls();
|
||||
parse_test_from_file();
|
||||
}
|
||||
Reference in New Issue
Block a user