C codegen
This commit is contained in:
74
ast.c
74
ast.c
@@ -1,4 +1,6 @@
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Decls
|
||||
//-----------------------------------------------------------------------------
|
||||
function Decl *
|
||||
decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
|
||||
Decl *result = arena_push_struct(&p->main_arena, Decl);
|
||||
@@ -9,9 +11,10 @@ decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
|
||||
}
|
||||
|
||||
function Decl *
|
||||
decl_struct(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
|
||||
decl_struct(Parser *p, Decl_Kind kind, Token *pos, Intern_String name, Decl_Struct_Kind struct_kind){
|
||||
assert(kind == DECL_Struct || kind == DECL_Union);
|
||||
Decl *result = decl_new(p, kind, pos, name);
|
||||
result->struct_decl.kind = struct_kind;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -37,6 +40,23 @@ decl_variable(Parser *p, Token *pos, Intern_String name, Typespec *typespec, Exp
|
||||
return result;
|
||||
}
|
||||
|
||||
function Decl *
|
||||
decl_function(Parser *p, Token *pos, Intern_String name, Typespec *ret){
|
||||
Decl *result = decl_new(p, DECL_Function, pos, name);
|
||||
result->function_decl.ret = ret;
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
decl_function_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Typespec *type){
|
||||
assert(parent->kind == DECL_Function);
|
||||
Decl_Function_Arg *result = arena_push_struct(&p->main_arena, Decl_Function_Arg);
|
||||
result->name = name;
|
||||
result->typespec = type;
|
||||
result->pos = pos;
|
||||
SLLQueuePush(parent->function_decl.first, parent->function_decl.last, result);
|
||||
}
|
||||
|
||||
function void
|
||||
decl_enum_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){
|
||||
assert(parent->kind == DECL_Enum);
|
||||
@@ -61,6 +81,15 @@ decl_list_push(Decl *parent, Decl *child){
|
||||
SLLQueuePush(parent->list.first, parent->list.last, child);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Notes
|
||||
//-----------------------------------------------------------------------------
|
||||
function void
|
||||
decl_pass_notes(Decl *a, Note *b){
|
||||
a->first_note = b->first;
|
||||
a->last_note = b->last;
|
||||
}
|
||||
|
||||
function Note *
|
||||
note_push_new(Parser *p, Note *parent, Token *pos, Intern_String name, Expr *expr){
|
||||
Note *result = arena_push_struct(&p->main_arena, Note);
|
||||
@@ -71,12 +100,38 @@ note_push_new(Parser *p, Note *parent, Token *pos, Intern_String name, Expr *exp
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
decl_pass_notes(Decl *a, Note *b){
|
||||
a->first_note = b->first;
|
||||
a->last_note = b->last;
|
||||
function Note *
|
||||
find_note(Note *first, String string){
|
||||
for(Note *n = first; n; n=n->next){
|
||||
if(string_compare(string, n->name.s)){
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function String
|
||||
find_string_note(Note *first, String string, String default_string){
|
||||
Note *note = find_note(first, string);
|
||||
if(note){
|
||||
return note->expr->token->intern_val.s;
|
||||
}
|
||||
return default_string;
|
||||
}
|
||||
|
||||
function Note *
|
||||
decl_find_note(Decl *decl, String string){
|
||||
return find_note(decl->first_note, string);
|
||||
}
|
||||
|
||||
function String
|
||||
decl_find_string_note(Decl *decl, String string, String default_string){
|
||||
return find_string_note(decl->first_note, string, default_string);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Typespec
|
||||
//-----------------------------------------------------------------------------
|
||||
function Typespec *
|
||||
typespec_new(Parser *p, Typespec_Kind kind, Token *pos){
|
||||
Typespec *result = arena_push_struct(&p->main_arena, Typespec);
|
||||
@@ -85,13 +140,6 @@ typespec_new(Parser *p, Typespec_Kind kind, Token *pos){
|
||||
return result;
|
||||
}
|
||||
|
||||
function Typespec *
|
||||
typespec_struct(Parser *p, Token *pos, Decl *aggregate){
|
||||
Typespec *result = typespec_new(p, TS_Struct, pos);
|
||||
result->struct_spec = aggregate;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Typespec *
|
||||
typespec_name(Parser *p, Token *pos, Intern_String name){
|
||||
Typespec *result = typespec_new(p, TS_Name, pos);
|
||||
|
||||
64
ast.h
64
ast.h
@@ -1,7 +1,9 @@
|
||||
typedef struct Decl_Enum_Child Decl_Enum_Child;
|
||||
typedef struct Decl_Function_Arg Decl_Function_Arg;
|
||||
typedef struct Typespec Typespec;
|
||||
typedef struct Decl Decl;
|
||||
typedef struct Note Note;
|
||||
typedef struct Stmt Stmt;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type specifier
|
||||
@@ -12,7 +14,6 @@ typedef enum Typespec_Kind{
|
||||
TS_Pointer,
|
||||
TS_Array,
|
||||
TS_Function,
|
||||
TS_Struct,
|
||||
}Typespec_Kind;
|
||||
|
||||
struct Typespec{
|
||||
@@ -21,7 +22,6 @@ struct Typespec{
|
||||
Token *pos;
|
||||
union{
|
||||
Intern_String name;
|
||||
Decl *struct_spec;
|
||||
struct{
|
||||
Typespec *first;
|
||||
Typespec *last;
|
||||
@@ -58,9 +58,22 @@ typedef enum Decl_Kind{
|
||||
DECL_Enum,
|
||||
DECL_Variable,
|
||||
DECL_Typedef,
|
||||
DECL_Function,
|
||||
DECL_List,
|
||||
}Decl_Kind;
|
||||
|
||||
typedef enum Decl_Struct_Kind{
|
||||
STRUCT_Base ,
|
||||
STRUCT_Nested,
|
||||
}Decl_Struct_Kind;
|
||||
|
||||
struct Decl_Function_Arg{
|
||||
Decl_Function_Arg *next;
|
||||
Intern_String name;
|
||||
Typespec *typespec;
|
||||
Token *pos;
|
||||
};
|
||||
|
||||
struct Decl_Enum_Child{
|
||||
Decl_Enum_Child *next;
|
||||
Intern_String name;
|
||||
@@ -73,9 +86,10 @@ struct Decl_Enum_Child{
|
||||
|
||||
struct Decl{
|
||||
Decl_Kind kind;
|
||||
Decl *next;
|
||||
|
||||
Intern_String name;
|
||||
Token *pos;
|
||||
Decl *next;
|
||||
|
||||
Note *first_note;
|
||||
Note *last_note;
|
||||
@@ -87,6 +101,7 @@ struct Decl{
|
||||
Typespec *typespec;
|
||||
}enum_decl;
|
||||
struct{
|
||||
Decl_Struct_Kind kind;
|
||||
Decl *first;
|
||||
Decl *last;
|
||||
} struct_decl;
|
||||
@@ -97,6 +112,11 @@ struct Decl{
|
||||
struct{
|
||||
Typespec *type;
|
||||
}typedef_decl;
|
||||
struct{
|
||||
Decl_Function_Arg *first;
|
||||
Decl_Function_Arg *last ;
|
||||
Typespec *ret;
|
||||
}function_decl;
|
||||
struct{
|
||||
Decl *first;
|
||||
Decl *last;
|
||||
@@ -104,3 +124,41 @@ struct Decl{
|
||||
};
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Statements
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef enum Stmt_Kind{
|
||||
STMT_None,
|
||||
STMT_Decl,
|
||||
STMT_Expr,
|
||||
STMT_Return,
|
||||
STMT_If,
|
||||
STMT_For,
|
||||
}Stmt_Kind;
|
||||
|
||||
typedef struct Stmt_List Stmt_List;
|
||||
struct Stmt_List{
|
||||
Stmt *first;
|
||||
Stmt *last;
|
||||
};
|
||||
|
||||
typedef struct Stmt_If Stmt_If;
|
||||
struct Stmt_If{
|
||||
Stmt_If *next;
|
||||
Expr *expr;
|
||||
union{
|
||||
struct{Stmt *first; Stmt *last;};
|
||||
Stmt_List *list;
|
||||
};
|
||||
};
|
||||
|
||||
struct Stmt{
|
||||
Stmt_Kind kind;
|
||||
Stmt *next;
|
||||
union{
|
||||
Decl *decl;
|
||||
Expr *expr;
|
||||
Stmt_If *if_stmt;
|
||||
Stmt_List *list;
|
||||
};
|
||||
};
|
||||
|
||||
126
codegen_c.c
Normal file
126
codegen_c.c
Normal file
@@ -0,0 +1,126 @@
|
||||
function void gen_decl(Parser *p, Decl *node);
|
||||
|
||||
function void
|
||||
gen_typespec(Parser *p, Typespec *spec, B32 is_left){
|
||||
switch(spec->kind) {
|
||||
|
||||
case TS_Name: {
|
||||
if(is_left) lex_print("%s", spec->name.s.str);
|
||||
} break;
|
||||
|
||||
case TS_Pointer: {
|
||||
gen_typespec(p, spec->base,is_left);
|
||||
if(is_left) lex_print("*");
|
||||
} break;
|
||||
|
||||
case TS_Array: {
|
||||
gen_typespec(p, spec->array_spec.base,is_left);
|
||||
if(!is_left){
|
||||
lex_print("[");
|
||||
expr_print(p, spec->array_spec.size);
|
||||
lex_print("]");
|
||||
}
|
||||
} break;
|
||||
|
||||
case TS_Function: {
|
||||
invalid_codepath;
|
||||
} break;
|
||||
default: {invalid_codepath;} break;
|
||||
}
|
||||
}
|
||||
|
||||
function Typespec *
|
||||
typespec_get_func(Typespec *type){
|
||||
switch(type->kind){
|
||||
|
||||
case TS_Name:{return 0;} break;
|
||||
case TS_Pointer:{return typespec_get_func(type->base);} break;
|
||||
case TS_Array:{return typespec_get_func(type->array_spec.base);} break;
|
||||
case TS_Function:{return type;} break;
|
||||
default: {invalid_codepath;} break;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function void
|
||||
gen_decl(Parser *p, Decl *node){
|
||||
|
||||
switch(node->kind) {
|
||||
case DECL_List: {
|
||||
for(Decl *n = node->list.first; n; n=n->next){
|
||||
gen_decl(p,n);
|
||||
lex_new_line();
|
||||
}
|
||||
} break;
|
||||
|
||||
case DECL_Variable:{
|
||||
Typespec *func = typespec_get_func(node->variable_decl.type);
|
||||
if(!func){
|
||||
gen_typespec(p, node->variable_decl.type, true);
|
||||
lex_print(" %s", node->name.s.str);
|
||||
gen_typespec(p, node->variable_decl.type, false);
|
||||
}
|
||||
else{
|
||||
gen_typespec(p, func->function_spec.ret, true);
|
||||
lex_print("(*");
|
||||
lex_print("%s", node->name.s.str);
|
||||
lex_print(")");
|
||||
lex_print("(");
|
||||
for(Typespec *t = func->function_spec.first; t; t=t->next){
|
||||
gen_typespec(p, t, true);
|
||||
gen_typespec(p, t, false);
|
||||
if(t != func->function_spec.last) lex_print(", ");
|
||||
}
|
||||
lex_print(")");
|
||||
}
|
||||
print_assign_expr(p,node->variable_decl.expr);
|
||||
lex_print(";");
|
||||
} break;
|
||||
|
||||
case DECL_Typedef:{
|
||||
lex_print("typedef %s ", node->name.s.str);
|
||||
gen_typespec(p, node->typedef_decl.type, true);
|
||||
gen_typespec(p, node->typedef_decl.type, false);
|
||||
lex_print(";");
|
||||
} break;
|
||||
|
||||
case DECL_Struct:
|
||||
case DECL_Union :{
|
||||
U8 *struct_name = node->kind==DECL_Struct ? (U8*)"struct" : (U8*)"union";
|
||||
U8 *name = node->name.s.str;
|
||||
if(node->struct_decl.kind == STRUCT_Base)
|
||||
lex_print("typedef %s %s %s;\n", struct_name, name, name);
|
||||
lex_print("%s %s{\n", struct_name, name?name:(U8*)"");
|
||||
for(Decl *n = node->struct_decl.first; n; n=n->next){
|
||||
gen_decl(p, n);
|
||||
lex_print("\n");
|
||||
}
|
||||
lex_print("};");
|
||||
if(node->struct_decl.kind == STRUCT_Base)
|
||||
lex_print("\n");
|
||||
} break;
|
||||
|
||||
case DECL_Enum:{
|
||||
lex_print("enum %s", node->name.s.str);
|
||||
if(!intern_compare(node->enum_decl.typespec->name, intern_s64)){
|
||||
lex_print(" : ");
|
||||
lex_print("%s", node->enum_decl.typespec->name.s.str);
|
||||
}
|
||||
lex_print("{\n");
|
||||
|
||||
String prefix = decl_find_string_note(node, lit("prefix"), string_empty);
|
||||
for(Decl_Enum_Child *n = node->enum_decl.first; n; n=n->next){
|
||||
lex_print("%.*s%s", (int)prefix.len, prefix.str, n->name.s.str);
|
||||
print_assign_expr(p, n->expr);
|
||||
lex_print(",\n");
|
||||
}
|
||||
|
||||
lex_print("};\n");
|
||||
} break;
|
||||
|
||||
default: {invalid_codepath;} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
common.c
1
common.c
@@ -1,3 +1,4 @@
|
||||
global String string_empty;
|
||||
|
||||
function S64
|
||||
clamp_top_s64(S64 val, S64 max){
|
||||
|
||||
17
main.c
17
main.c
@@ -26,6 +26,7 @@ global FILE *global_output_file;
|
||||
#include "parse_expr.c"
|
||||
#include "parse_decl.c"
|
||||
#include "print.c"
|
||||
#include "codegen_c.c"
|
||||
|
||||
function void
|
||||
lex_test(){
|
||||
@@ -96,24 +97,16 @@ parser_test(){
|
||||
parser_lex_stream(&p, exprs[i], lit("File"));
|
||||
Expr *expr = parse_expr(&p);
|
||||
assert(expr);
|
||||
expr_print(&p, expr);
|
||||
lex_print("\n");
|
||||
//expr_print(&p, expr);
|
||||
//lex_print("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
String string
|
||||
= lit(
|
||||
"@test Thing2 :: struct { thing: union{a:U32;}; _: union{ thing: U32*; }; }"
|
||||
"Thing :: enum: U32 { @str=\"as\" Thing = 32, Thing2 = 15<<2, }"
|
||||
"Thing :: struct{ identi: U64*[32]; InnerStruct :: struct { t: U32; } var: InnerStruct; pp :: enum { Thing_1 } }"
|
||||
"thing:(S64*,U64) U32*@[10]; }"
|
||||
);
|
||||
*/
|
||||
String string = os_read_file(lit("test.cc"));
|
||||
parser_lex_stream(&p, string, lit("Parse"));
|
||||
Decl *decls = parse(&p);
|
||||
assert(decls->list.first);
|
||||
print_decl(&p, decls);
|
||||
gen_decl(&p, decls);
|
||||
|
||||
}
|
||||
|
||||
function S32
|
||||
|
||||
409
output.cc
409
output.cc
@@ -1,246 +1,243 @@
|
||||
(((534>43)?435:42),234,((S64)32),Thing[10][2],Thing((1,2)))
|
||||
(4+(2*53))
|
||||
((4+2)*53)
|
||||
(++5)
|
||||
(--5)
|
||||
(-5)
|
||||
(+5)
|
||||
(sizeof(32)+sizeof(S32*))
|
||||
((S64**)5)
|
||||
(((S64)5)+3)
|
||||
((534>43)?435:42)
|
||||
typedef struct OpenGL OpenGL;
|
||||
struct OpenGL{
|
||||
void(*glVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoid*);
|
||||
void(*glBindTexture)(GLenum, GLuint);
|
||||
void(*glDrawArrays)(GLenum, GLint, GLsizei);
|
||||
};
|
||||
|
||||
typedef struct OS_Memory OS_Memory;
|
||||
struct OS_Memory{
|
||||
data: void*;
|
||||
commit: SizeU;
|
||||
reserve: SizeU;
|
||||
void* data;
|
||||
SizeU commit;
|
||||
SizeU reserve;
|
||||
};
|
||||
|
||||
typedef struct Arena Arena;
|
||||
struct Arena{
|
||||
@using memory: OS_Memory;
|
||||
len: U64;
|
||||
alignment: U64;
|
||||
OS_Memory memory;
|
||||
U64 len;
|
||||
U64 alignment;
|
||||
};
|
||||
|
||||
typedef struct String String;
|
||||
struct String{
|
||||
str: U8*;
|
||||
len: S64;
|
||||
U8* str;
|
||||
S64 len;
|
||||
};
|
||||
|
||||
typedef Intern_String String;
|
||||
@stringify @prefix = TK_ enum Token_Kind : S64{
|
||||
@str = End of stream End,
|
||||
@str = * Mul,
|
||||
@str = / Div,
|
||||
@str = + Add,
|
||||
@str = - Sub,
|
||||
@str = % Mod,
|
||||
@str = & BitAnd,
|
||||
@str = | BitOr,
|
||||
@str = ^ BitXor,
|
||||
@str = ~ Neg,
|
||||
@str = ! Not,
|
||||
@str = ( OpenParen,
|
||||
@str = CloseParen,
|
||||
@str = { OpenBrace,
|
||||
@str = } CloseBrace,
|
||||
@str = [ OpenBracket,
|
||||
@str = ] CloseBracket,
|
||||
@str = , Comma,
|
||||
@str = # Pound,
|
||||
@str = ? Question,
|
||||
@str = ... ThreeDots,
|
||||
@str = ; Semicolon,
|
||||
@str = . Dot,
|
||||
@str = < LesserThen,
|
||||
@str = > GreaterThen,
|
||||
@str = : Colon,
|
||||
@str = = Assign,
|
||||
@str = /= DivAssign,
|
||||
@str = *= MulAssign,
|
||||
@str = %= ModAssign,
|
||||
@str = -= SubAssign,
|
||||
@str = += AddAssign,
|
||||
@str = &= AndAssign,
|
||||
@str = |= OrAssign,
|
||||
@str = ^= XorAssign,
|
||||
@str = <<= LeftShiftAssign,
|
||||
@str = >>= RightShiftAssign,
|
||||
@str = :: DoubleColon,
|
||||
@str = @ At,
|
||||
@str = -- Decrement,
|
||||
@str = ++ Increment,
|
||||
@str = -- PostDecrement,
|
||||
@str = ++ PostIncrement,
|
||||
@str = <= LesserThenOrEqual,
|
||||
@str = >= GreaterThenOrEqual,
|
||||
@str = == Equals,
|
||||
@str = && And,
|
||||
@str = || Or,
|
||||
@str = != NotEquals,
|
||||
@str = << LeftShift,
|
||||
@str = >> RightShift,
|
||||
@str = -> Arrow,
|
||||
@str = sizeof ExprSizeof,
|
||||
DocComment,
|
||||
Comment,
|
||||
Identifier,
|
||||
StringLit,
|
||||
U8Lit,
|
||||
Character,
|
||||
Error,
|
||||
Float,
|
||||
Int,
|
||||
Keyword,
|
||||
enum Token_Kind{
|
||||
TK_End,
|
||||
TK_Mul,
|
||||
TK_Div,
|
||||
TK_Add,
|
||||
TK_Sub,
|
||||
TK_Mod,
|
||||
TK_BitAnd,
|
||||
TK_BitOr,
|
||||
TK_BitXor,
|
||||
TK_Neg,
|
||||
TK_Not,
|
||||
TK_OpenParen,
|
||||
TK_CloseParen,
|
||||
TK_OpenBrace,
|
||||
TK_CloseBrace,
|
||||
TK_OpenBracket,
|
||||
TK_CloseBracket,
|
||||
TK_Comma,
|
||||
TK_Pound,
|
||||
TK_Question,
|
||||
TK_ThreeDots,
|
||||
TK_Semicolon,
|
||||
TK_Dot,
|
||||
TK_LesserThen,
|
||||
TK_GreaterThen,
|
||||
TK_Colon,
|
||||
TK_Assign,
|
||||
TK_DivAssign,
|
||||
TK_MulAssign,
|
||||
TK_ModAssign,
|
||||
TK_SubAssign,
|
||||
TK_AddAssign,
|
||||
TK_AndAssign,
|
||||
TK_OrAssign,
|
||||
TK_XorAssign,
|
||||
TK_LeftShiftAssign,
|
||||
TK_RightShiftAssign,
|
||||
TK_DoubleColon,
|
||||
TK_At,
|
||||
TK_Decrement,
|
||||
TK_Increment,
|
||||
TK_PostDecrement,
|
||||
TK_PostIncrement,
|
||||
TK_LesserThenOrEqual,
|
||||
TK_GreaterThenOrEqual,
|
||||
TK_Equals,
|
||||
TK_And,
|
||||
TK_Or,
|
||||
TK_NotEquals,
|
||||
TK_LeftShift,
|
||||
TK_RightShift,
|
||||
TK_Arrow,
|
||||
TK_ExprSizeof,
|
||||
TK_DocComment,
|
||||
TK_Comment,
|
||||
TK_Identifier,
|
||||
TK_StringLit,
|
||||
TK_U8Lit,
|
||||
TK_Character,
|
||||
TK_Error,
|
||||
TK_Float,
|
||||
TK_Int,
|
||||
TK_Keyword,
|
||||
};
|
||||
|
||||
typedef struct Token Token;
|
||||
struct Token{
|
||||
kind: Token_Kind;
|
||||
@using string: String;
|
||||
val: union {
|
||||
integer: S64;
|
||||
error: String;
|
||||
intern: Intern_String;
|
||||
};
|
||||
|
||||
file: String;
|
||||
line: S64;
|
||||
line_begin: U8*;
|
||||
Token_Kind kind;
|
||||
String string;
|
||||
union {
|
||||
S64 integer_val;
|
||||
String error_val;
|
||||
Intern_String intern_val;
|
||||
};
|
||||
String file;
|
||||
S64 line;
|
||||
U8* line_begin;
|
||||
};
|
||||
|
||||
typedef struct Tokens Tokens;
|
||||
struct Tokens{
|
||||
@array tokens: Token*;
|
||||
iter: S64;
|
||||
Token* tokens;
|
||||
S64 iter;
|
||||
};
|
||||
|
||||
typedef struct Lex_Stream Lex_Stream;
|
||||
struct Lex_Stream{
|
||||
stream: U8*;
|
||||
line_begin: U8*;
|
||||
filename: String;
|
||||
line: S64;
|
||||
U8* stream;
|
||||
U8* line_begin;
|
||||
String filename;
|
||||
S64 line;
|
||||
};
|
||||
|
||||
@prefix = EK_ enum Expr_Kind : S64{
|
||||
None,
|
||||
Atom,
|
||||
Unary,
|
||||
Binary,
|
||||
Ternary,
|
||||
Cast,
|
||||
List,
|
||||
Call,
|
||||
Index,
|
||||
enum Expr_Kind{
|
||||
EK_None,
|
||||
EK_Atom,
|
||||
EK_Unary,
|
||||
EK_Binary,
|
||||
EK_Ternary,
|
||||
EK_Cast,
|
||||
EK_List,
|
||||
EK_Call,
|
||||
EK_Index,
|
||||
};
|
||||
|
||||
typedef struct Expr Expr;
|
||||
struct Expr{
|
||||
kind: Expr_Kind;
|
||||
token: Token*;
|
||||
next: Expr*;
|
||||
_: union {
|
||||
cast_val: struct {
|
||||
type: AST_Node*;
|
||||
expr: Expr*;
|
||||
Expr_Kind kind;
|
||||
Token* token;
|
||||
Expr* next;
|
||||
union {
|
||||
struct cast_val{
|
||||
AST_Node* type;
|
||||
Expr* expr;
|
||||
};
|
||||
struct list{
|
||||
Expr* first;
|
||||
Expr* last;
|
||||
};
|
||||
struct call{
|
||||
Expr* atom;
|
||||
Expr* list;
|
||||
};
|
||||
struct index{
|
||||
Expr* atom;
|
||||
Expr* index;
|
||||
};
|
||||
struct unary{
|
||||
Expr* expr;
|
||||
};
|
||||
struct binary{
|
||||
Expr* left;
|
||||
Expr* right;
|
||||
};
|
||||
struct ternary{
|
||||
Expr* cond;
|
||||
Expr* on_true;
|
||||
Expr* on_false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
list: struct {
|
||||
first: Expr*;
|
||||
last: Expr*;
|
||||
};
|
||||
|
||||
call: struct {
|
||||
atom: Expr*;
|
||||
list: Expr*;
|
||||
};
|
||||
|
||||
index: struct {
|
||||
atom: Expr*;
|
||||
index: Expr*;
|
||||
};
|
||||
|
||||
unary: struct {
|
||||
expr: Expr*;
|
||||
};
|
||||
|
||||
binary: struct {
|
||||
left: Expr*;
|
||||
right: Expr*;
|
||||
};
|
||||
|
||||
ternary: struct {
|
||||
cond: Expr*;
|
||||
on_true: Expr*;
|
||||
on_false: Expr*;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@prefix = AK_ enum AST_Kind : S64{
|
||||
None,
|
||||
BaseType,
|
||||
Typedef,
|
||||
Enum,
|
||||
Struct,
|
||||
Union,
|
||||
Note,
|
||||
List,
|
||||
Pointer,
|
||||
Array,
|
||||
Function,
|
||||
Variable,
|
||||
EnumChild,
|
||||
enum AST_Kind{
|
||||
AK_None,
|
||||
AK_BaseType,
|
||||
AK_Typedef,
|
||||
AK_Enum,
|
||||
AK_Struct,
|
||||
AK_Union,
|
||||
AK_Note,
|
||||
AK_List,
|
||||
AK_Pointer,
|
||||
AK_Array,
|
||||
AK_Function,
|
||||
AK_Variable,
|
||||
AK_EnumChild,
|
||||
};
|
||||
|
||||
typedef struct AST_Node AST_Node;
|
||||
struct AST_Node{
|
||||
kind: AST_Kind;
|
||||
pos: Token*;
|
||||
name: Intern_String;
|
||||
next: AST_Node*;
|
||||
next_scope: AST_Node*;
|
||||
first_note: AST_Node*;
|
||||
last_note: AST_Node*;
|
||||
first_child: AST_Node*;
|
||||
last_child: AST_Node*;
|
||||
_: union {
|
||||
base_type_size: SizeU;
|
||||
pointer: AST_Node*;
|
||||
typedef_type: AST_Node*;
|
||||
variable_type: AST_Node*;
|
||||
func_return_type: AST_Node*;
|
||||
};
|
||||
|
||||
AST_Kind kind;
|
||||
Token* pos;
|
||||
Intern_String name;
|
||||
AST_Node* next;
|
||||
AST_Node* next_scope;
|
||||
AST_Node* first_note;
|
||||
AST_Node* last_note;
|
||||
AST_Node* first_child;
|
||||
AST_Node* last_child;
|
||||
union {
|
||||
SizeU base_type_size;
|
||||
AST_Node* pointer;
|
||||
AST_Node* typedef_type;
|
||||
AST_Node* variable_type;
|
||||
AST_Node* func_return_type;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct Parser_Error Parser_Error;
|
||||
struct Parser_Error{
|
||||
next: Parser_Error*;
|
||||
message: String;
|
||||
token: Token*;
|
||||
Parser_Error* next;
|
||||
String message;
|
||||
Token* token;
|
||||
};
|
||||
|
||||
typedef struct Scope Scope;
|
||||
struct Scope{
|
||||
next: Scope*;
|
||||
first: AST_Node*;
|
||||
last: AST_Node*;
|
||||
Scope* next;
|
||||
AST_Node* first;
|
||||
AST_Node* last;
|
||||
};
|
||||
|
||||
typedef struct Parser Parser;
|
||||
struct Parser{
|
||||
main_arena: Arena;
|
||||
intern_table_arena: Arena;
|
||||
symbol_table_arena: Arena;
|
||||
scope_free_list: Scope*;
|
||||
scope_stack: Scope*;
|
||||
global_scope: Scope*;
|
||||
symbols_inserted: S64;
|
||||
symbols_count: S64;
|
||||
symbols: AST_Node*;
|
||||
interns: Intern_String*;
|
||||
interns_in_bytes: S64;
|
||||
interns_inserted: S64;
|
||||
interns_count: S64;
|
||||
first_keyword: U8*;
|
||||
last_keyword: U8*;
|
||||
@sllqueue default: Parser_Error;
|
||||
@sllqueue error: Parser_Error;
|
||||
@using token_array: Tokens;
|
||||
Arena main_arena;
|
||||
Arena intern_table_arena;
|
||||
Arena symbol_table_arena;
|
||||
Scope* scope_free_list;
|
||||
Scope* scope_stack;
|
||||
Scope* global_scope;
|
||||
S64 symbols_inserted;
|
||||
S64 symbols_count;
|
||||
AST_Node* symbols;
|
||||
Intern_String* interns;
|
||||
S64 interns_in_bytes;
|
||||
S64 interns_inserted;
|
||||
S64 interns_count;
|
||||
U8* first_keyword;
|
||||
U8* last_keyword;
|
||||
Parser_Error default;
|
||||
Parser_Error error;
|
||||
Tokens token_array;
|
||||
};
|
||||
|
||||
|
||||
81
parse_decl.c
81
parse_decl.c
@@ -1,15 +1,7 @@
|
||||
function Decl *parse_decl(Parser *p);
|
||||
function Decl *parse_struct(Parser *p, Token *name, Decl_Kind kind);
|
||||
function Decl *parse_struct(Parser *p, Token *name, Decl_Kind kind, Decl_Struct_Kind);
|
||||
function Typespec *parse_type(Parser *p);
|
||||
|
||||
function Typespec *
|
||||
parse_type_struct(Parser *p, Token *token){
|
||||
Decl_Kind kind = intern_compare(token->intern_val, keyword_struct) ? DECL_Struct : DECL_Union;
|
||||
Decl *decl = parse_struct(p, token, kind);
|
||||
decl->name = (Intern_String){};
|
||||
return typespec_struct(p, token, decl);
|
||||
}
|
||||
|
||||
function Typespec *
|
||||
parse_type_function(Parser *p, Token *token){
|
||||
Typespec *result = typespec_function(p, token, 0);
|
||||
@@ -35,14 +27,13 @@ parse_type_function(Parser *p, Token *token){
|
||||
|
||||
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_keyword(p, keyword_struct)) || (token = token_match_keyword(p, keyword_union))){
|
||||
result = parse_type_struct(p, token);
|
||||
}
|
||||
else if((token = token_match(p, TK_OpenParen))){
|
||||
result = parse_type_function(p, token);
|
||||
}
|
||||
@@ -51,6 +42,7 @@ parse_type(Parser *p){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse Pointer/Array
|
||||
for(;;){
|
||||
if((token = token_match(p, TK_Mul))){
|
||||
result = typespec_pointer(p, token, result);
|
||||
@@ -65,6 +57,8 @@ parse_type(Parser *p){
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -111,6 +105,14 @@ parse_notes(Parser *p){
|
||||
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;
|
||||
@@ -132,18 +134,35 @@ parse_enum(Parser *p, Token *name){
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_struct(Parser *p, Token *name, Decl_Kind kind){
|
||||
Decl *result = decl_struct(p, kind, name, name->intern_val);
|
||||
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))){
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
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;
|
||||
@@ -163,13 +182,29 @@ parse_typedef(Parser *p, Token *name){
|
||||
return decl_typedef(p, name, name->intern_val, type);
|
||||
}
|
||||
|
||||
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);
|
||||
/*
|
||||
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((name = token_match(p, TK_Identifier)))
|
||||
decl_function_push(p, result, name, name->intern_val, parse_type(p));
|
||||
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);
|
||||
|
||||
token_expect(p, TK_OpenBrace);
|
||||
parse_stmt_list(p, result);
|
||||
token_expect(p, TK_CloseBrace);
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
function Decl *
|
||||
parse_decl(Parser *p){
|
||||
@@ -179,10 +214,10 @@ parse_decl(Parser *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);
|
||||
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);
|
||||
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));
|
||||
@@ -193,8 +228,6 @@ parse_decl(Parser *p){
|
||||
}
|
||||
else if(token_peek_is(p, 1, TK_Colon)){
|
||||
if(token_peek_is(p, 2, TK_Identifier) ||
|
||||
token_peek_is_keyword(p, 2, keyword_union) ||
|
||||
token_peek_is_keyword(p, 2, keyword_struct) ||
|
||||
token_peek_is(p, 2, TK_OpenParen)){
|
||||
result = parse_variable(p, parse_get_token_name(p,1));
|
||||
}
|
||||
|
||||
3
parser.c
3
parser.c
@@ -95,6 +95,9 @@ intern_tokens(Parser *p){
|
||||
t->kind = TK_Keyword;
|
||||
}
|
||||
}
|
||||
else if(t->kind == TK_U8Lit){
|
||||
t->intern_val = intern_string(p, t->string);
|
||||
}
|
||||
else if(t->kind == TK_Error){
|
||||
parser_push_error(p, t, (char *)t->error_val.str);
|
||||
}
|
||||
|
||||
7
print.c
7
print.c
@@ -91,9 +91,6 @@ expr_print(Parser *p, Expr *expr){
|
||||
}
|
||||
}
|
||||
|
||||
global S64 indent;
|
||||
|
||||
|
||||
function B32
|
||||
print_typespec(Parser *p, Typespec *spec){
|
||||
switch(spec->kind) {
|
||||
@@ -101,10 +98,6 @@ print_typespec(Parser *p, Typespec *spec){
|
||||
lex_print("%s", spec->name.s.str);
|
||||
} break;
|
||||
|
||||
case TS_Struct:{
|
||||
print_decl(p, spec->struct_spec);
|
||||
return false;
|
||||
} break;
|
||||
|
||||
case TS_Pointer: {
|
||||
print_typespec(p, spec->base);
|
||||
|
||||
34
sym.h
Normal file
34
sym.h
Normal file
@@ -0,0 +1,34 @@
|
||||
typedef enum Symbol_Kind{
|
||||
SYM_None,
|
||||
SYM_Decl,
|
||||
SYM_Type,
|
||||
}Symbol_Kind;
|
||||
|
||||
typedef enum Symbol_State{
|
||||
SYM_STATE_Used,
|
||||
SYM_STATE_Declared,
|
||||
}Symbol_State;
|
||||
|
||||
typedef struct Symbol{
|
||||
Symbol_Kind kind;
|
||||
Symbol_State state;
|
||||
Symbol *next;
|
||||
|
||||
union{
|
||||
Decl *decl;
|
||||
struct{
|
||||
Typespec *spec;
|
||||
} type;
|
||||
};
|
||||
} Symbol;
|
||||
|
||||
// First stage would add all symbols as underspecified to the table
|
||||
// Every encountered typespec would be added to the table as either specified or
|
||||
// just as encountered name
|
||||
//
|
||||
// Then second stage would loop over all of them and report errors on all symbols that were
|
||||
// found in the wild but not declared
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
38
test.cc
38
test.cc
@@ -1,5 +1,11 @@
|
||||
#if 0
|
||||
|
||||
OpenGL :: struct{
|
||||
glVertexAttribPointer: (GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoid*);
|
||||
glBindTexture: (GLenum, GLuint);
|
||||
glDrawArrays: (GLenum, GLint, GLsizei);
|
||||
}
|
||||
|
||||
OS_Memory::struct{
|
||||
data: void*;
|
||||
commit: SizeU;
|
||||
@@ -89,11 +95,11 @@ Token_Kind::enum{
|
||||
Token::struct{
|
||||
kind:Token_Kind;
|
||||
@using string:String;
|
||||
val: union{
|
||||
integer:S64;
|
||||
error:String;
|
||||
intern:Intern_String;
|
||||
};
|
||||
union{
|
||||
integer_val:S64;
|
||||
error_val:String;
|
||||
intern_val:Intern_String;
|
||||
}
|
||||
file:String;
|
||||
line:S64;
|
||||
line_begin:U8*;
|
||||
@@ -128,36 +134,36 @@ Expr:: struct{
|
||||
kind: Expr_Kind;
|
||||
token: Token*;
|
||||
next : Expr*;
|
||||
_: union{
|
||||
union{
|
||||
cast_val: struct{
|
||||
type: AST_Node*;
|
||||
expr: Expr*;
|
||||
};
|
||||
}
|
||||
list: struct{
|
||||
first: Expr *;
|
||||
last: Expr *;
|
||||
};
|
||||
}
|
||||
call: struct{
|
||||
atom: Expr *;
|
||||
list: Expr *;
|
||||
};
|
||||
}
|
||||
index: struct{
|
||||
atom: Expr *;
|
||||
index: Expr *;
|
||||
};
|
||||
}
|
||||
unary: struct{
|
||||
expr: Expr* ;
|
||||
};
|
||||
}
|
||||
binary: struct{
|
||||
left: Expr* ;
|
||||
right: Expr* ;
|
||||
};
|
||||
}
|
||||
ternary: struct{
|
||||
cond: Expr* ;
|
||||
on_true: Expr*;
|
||||
on_false: Expr*;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@prefix="AK_"
|
||||
@@ -190,13 +196,13 @@ AST_Node::struct{
|
||||
|
||||
first_child: AST_Node*;
|
||||
last_child: AST_Node*;
|
||||
_:union{
|
||||
union{
|
||||
base_type_size: SizeU;
|
||||
pointer: AST_Node*;
|
||||
typedef_type: AST_Node*;
|
||||
variable_type: AST_Node*;
|
||||
func_return_type: AST_Node*;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Parser_Error :: struct{
|
||||
|
||||
Reference in New Issue
Block a user