Files
corelang/parse_decl.c
2022-05-06 10:13:16 +02:00

393 lines
10 KiB
C

function Decl *parse_decl(Parser *p);
function Decl *parse_struct(Parser *p, Token *name, Decl_Kind kind, Decl_Struct_Kind);
function Typespec *parse_type(Parser *p);
function Typespec *
parse_type_function(Parser *p, Token *token){
Typespec *result = typespec_function(p, token, 0);
if(!token_is(p, TK_CloseParen))
for(;;) {
// Optional name
if(token_is(p, TK_Identifier)){
if(token_peek_is(p, 1, TK_Colon)){
token_next(p);
token_next(p);
}
}
// Parse type
if(token_is(p, TK_Identifier)){
Typespec *arg = parse_type(p);
typespec_function_push(result, arg);
}
else if(!token_match(p, TK_Comma)){
break;
}
}
token_expect(p, TK_CloseParen);
if(token_is(p, TK_Identifier))
result->function_spec.ret = parse_type(p);
else
result->function_spec.ret = typespec_name(p, token_get(p), intern_void);
return result;
}
function Typespec *
parse_type(Parser *p){
// Parse as function type or normal
Token *token = 0;
Typespec *result = 0;
if((token = token_match(p, TK_Identifier))){
result = typespec_name(p, token, token->intern_val);
}
else if((token = token_match(p, TK_OpenParen))){
result = parse_type_function(p, token);
}
else{
parser_push_error(p, token, "Failed to parse type, unexpected token");
return 0;
}
// Parse Pointer/Array
for(;;){
if((token = token_match(p, TK_Mul))){
result = typespec_pointer(p, token, result);
}
else if((token = token_match(p, TK_OpenBracket))){
Expr *expr = parse_expr(p);
result = typespec_array(p, token, result, expr);
token_expect(p, TK_CloseBracket);
}
else if(token_match(p, TK_At)){
break;
}
else break;
}
return result;
}
function Expr *
parse_expr_assignment(Parser *p){
Expr *result = 0;
if(token_match(p, TK_Assign)){
result = parse_expr(p);
}
return result;
}
function void
parse_note_list(Parser *p, Note *parent) {
if(token_match(p, TK_OpenParen)) {
if(token_match(p, TK_CloseParen)){
return;
}
do {
Token *name = token_expect(p, TK_Identifier);
Note *current = note_push_new(p, parent, name, name->intern_val, 0);
parse_note_list(p, current);
if(token_match(p, TK_Assign)) {
current->expr = parse_expr(p);
}
} while(token_match(p, TK_Comma));
token_expect(p, TK_CloseParen);
}
}
function void
parse__notes(Parser *p, Note *result) {
while(token_match(p, TK_At)) {
Token *name = token_expect(p, TK_Identifier);
Note *current = note_push_new(p, result, name, name->intern_val, 0);
parse_note_list(p, current);
if(token_match(p, TK_Assign)) {
current->expr = parse_expr(p);
}
token_match(p, TK_Semicolon);
}
}
function Note
parse_notes(Parser *p){
Note result = {0};
parse__notes(p, &result);
return result;
}
function Token *
parse_get_token_name(Parser *p, S32 count){
Token *result = token_next(p);
for(S32 i = 0; i < count; i++)
token_next(p);
return result;
}
function Decl *
parse_enum(Parser *p, Token *name){
Typespec *type = 0;
if(token_match(p, TK_Colon)) type = parse_type(p);
else type = typespec_name(p, token_get(p), intern_s64);
Decl *result = decl_enum(p, name, name->intern_val, type);
token_expect(p, TK_OpenBrace);
do{
Note notes = parse_notes(p);
Token *token = token_match(p, TK_Identifier);
if(token){
Expr *expr = parse_expr_assignment(p);
decl_enum_push(p, result, token, token->intern_val, expr, &notes);
} else break;
} while(token_match(p, TK_Comma));
token_expect(p, TK_CloseBrace);
return result;
}
function Decl *
parse_struct(Parser *p, Token *name, Decl_Kind kind, Decl_Struct_Kind struct_kind){
Decl *result = decl_struct(p, kind, name, name->intern_val, struct_kind);
token_expect(p, TK_OpenBrace);
while(!token_is(p, TK_CloseBrace)){
Decl *decl = 0;
if((decl = parse_decl(p))){
}
else if(token_match_keyword(p, keyword_union)){
decl = parse_struct(p, token_get(p), DECL_Union, STRUCT_Nested);
}
else if(token_match_keyword(p, keyword_struct)){
decl = parse_struct(p, token_get(p), DECL_Struct, STRUCT_Nested);
}
else if(token_is(p, TK_Identifier) &&
token_peek_is(p, 1, TK_Colon) &&
token_peek_is_keyword(p, 2, keyword_union)){
decl = parse_struct(p, parse_get_token_name(p, 2), DECL_Union, STRUCT_Nested);
}
else if(token_is(p, TK_Identifier) &&
token_peek_is(p, 1, TK_Colon) &&
token_peek_is_keyword(p, 2, keyword_struct)){
decl = parse_struct(p, parse_get_token_name(p, 2), DECL_Struct, STRUCT_Nested);
}
else {
parser_push_error(p, token_get(p), "Unexpected token while parsing struct");
break;
}
if(decl) decl_struct_push(result, decl);
}
token_expect(p, TK_CloseBrace);
return result;
}
function Decl *
parse_variable(Parser *p, Token *name){
Typespec *type = parse_type(p);
Expr *expr = parse_expr_assignment(p);
return decl_variable(p, name, name->intern_val, type, expr);
}
function Decl *
parse_typedef(Parser *p, Token *name){
Typespec *type = parse_type(p);
return decl_typedef(p, name, name->intern_val, type);
}
function Stmt *
parse_stmt(Parser *p);
function Stmt *
parse_stmt_list(Parser *p){
Token *token = token_expect(p, TK_OpenBrace);
Stmt *result = stmt_list(p, token);
while(!token_match(p, TK_CloseBrace)) {
Stmt *stmt = parse_stmt(p);
stmt_push(result, stmt);
}
return result;
}
function Stmt *
parse_stmt(Parser *p){
Token *token = token_get(p);
Decl *decl = parse_decl(p);
if(decl){
Stmt *result = stmt_decl(p, token, decl);
return result;
}
else if(token_match_keyword(p, keyword_return)){
Expr *expr = parse_expr(p);
Stmt *result = stmt_return(p, token, expr);
token_expect(p, TK_Semicolon);
return result;
}
else if(token_match_keyword(p, keyword_if)){
Expr *expr = parse_expr(p);
Stmt *if_body = parse_stmt_list(p);
Stmt *result = stmt_if(p, token, if_body, expr);
Stmt *head = result;
while(token_match_keyword(p, keyword_else)){
if(token_match_keyword(p, keyword_if)){
expr = parse_expr(p);
if_body = parse_stmt_list(p);
head = head->next = stmt_if(p, token, if_body, expr);
}
else{
if_body = parse_stmt_list(p);
head = head->next = stmt_if(p, token, if_body, 0);
break;
}
}
return result;
}
else if((token_is(p, TK_OpenBrace))){
Stmt *result = parse_stmt_list(p);
return result;
}
else{
Expr *expr = parse_expr(p);
token_expect(p, TK_Semicolon);
return stmt_expr(p, token, expr);
}
}
function Decl *
parse_function(Parser *p, Token *name){
Decl *result = decl_function(p, name, name->intern_val, 0);
if(!token_is(p, TK_CloseParen)){
for(;;) {
if(token_peek_is(p, 1, TK_Colon)){
if(token_peek_is(p, 2, TK_Identifier) ||
token_peek_is(p, 2, TK_OpenParen)){
Token *name = parse_get_token_name(p,1);
Typespec *type = parse_type(p);
decl_function_push(p, result, name, name->intern_val, type);
}
}
else if(!token_match(p, TK_Comma))
break;
}
}
token_expect(p, TK_CloseParen);
if(token_is(p, TK_Identifier))
result->function_decl.ret = parse_type(p);
else
result->function_decl.ret = typespec_name(p, token_get(p), intern_void);
result->function_decl.body = parse_stmt_list(p);
return result;
}
function Decl *
parse_decl(Parser *p){
Decl *result = 0;
Note notes = parse_notes(p);
if(token_is(p, TK_Identifier)){
if(token_peek_is(p, 1, TK_DoubleColon)){
if(token_peek_is_keyword(p, 2, keyword_struct)){
result = parse_struct(p, parse_get_token_name(p,2), DECL_Struct, STRUCT_Base);
}
else if(token_peek_is_keyword(p, 2, keyword_union)){
result = parse_struct(p, parse_get_token_name(p,2), DECL_Union, STRUCT_Base);
}
else if(token_peek_is_keyword(p, 2, keyword_enum)){
result = parse_enum(p, parse_get_token_name(p,2));
}
else if(token_peek_is_keyword(p, 2, keyword_typedef)){
result = parse_typedef(p, parse_get_token_name(p,2));
}
else if(token_peek_is(p, 2, TK_OpenParen)){
result = parse_function(p, parse_get_token_name(p,2));
}
}
else if(token_peek_is(p, 1, TK_Colon)){
if(token_peek_is(p, 2, TK_Identifier) ||
token_peek_is(p, 2, TK_OpenParen)){
result = parse_variable(p, parse_get_token_name(p,1));
token_expect(p, TK_Semicolon);
}
}
}
if(result){
decl_pass_notes(result, &notes);
}
else if(notes.first != 0){
parser_push_error(p, token_get(p), "Detected notes that are not attached to anything");
}
return result;
}
function Decl *
parse(Parser *p){
Decl *result = decl_new(p, DECL_List, token_get(p), (Intern_String){0});
for(;;){
Decl *decl = 0;
if(token_is(p, TK_End)) {
break;
}
else if((decl = parse_decl(p))){
// Noop
}
else token_next(p);
if(decl){
decl_list_push(result, decl);
}
}
return result;
}
function void gen_stmt(Stmt *stmt);
function void gen_end();
function void gen_begin(Arena *arena, Parser *p);
function void expr_print(Parser *p, Expr *expr);
function void
parser_test(){
Parser p = {0};
{
parser_init(&p);
Intern_String a = intern_string(&p, lit("Thing"));
Intern_String b = intern_string(&p, lit("Thing"));
assert(a.s.str == b.s.str);
}
String exprs[] = {
lit("(534>43?435:42,234,cast(S64)32/*todo cast*/,Thing[10][2],Thing(1,2))"),
lit("(4+2*53)"),
lit("((4+2)*53)"),
lit("++5"),
lit("5--"), // @Todo(Krzosa):
lit("-5"),
lit("(+5)"),
lit("sizeof(32) + sizeof(:S32*)"),
lit("cast(S64**)5"),
lit("cast(S64)5+3"),
lit("534>43?435:42"),
};
for(S64 i = 0; i < buff_cap(exprs); i++){
parser_lex_stream(&p, exprs[i], lit("File"));
Expr *expr = parse_expr(&p);
assert(expr);
expr_print(&p, expr);
lex_print("\n");
}
String stmts[] = {
lit("Thing :: struct { test: int; } "),
lit("thing: S32 = 100; "),
lit("thing = thing + 10; "),
lit("thing++; "),
lit("{ thing_scoped: S32 = 10; thing_scoped += 10; } "),
};
for(S64 i = 0; i < buff_cap(stmts); i++){
parser_lex_stream(&p, stmts[i], lit("File"));
Stmt *stmt = parse_stmt(&p);
assert(stmt);
gen_begin(&p.scratch, &p);
gen_stmt(stmt);
gen_end();
lex_print("\n");
}
}