Swinging in a different direction, different syntax

This commit is contained in:
Krzosa Karol
2022-05-01 13:51:34 +02:00
parent 3a9b748fed
commit c5498b03ad
14 changed files with 903 additions and 116 deletions

68
ast.c
View File

@@ -15,12 +15,47 @@ ast_node_new(Parser *p, AST_Kind kind, Token *token, Intern_String name){
return node;
}
function AST_Node *
ast_note(Parser *p, Token *token, Intern_String name, Expr *expr){
AST_Node *node = ast_node_new(p, AK_Note, token, name);
node->expr = expr;
return node;
}
function AST_Node *
ast_enum(Parser *p, Token *token, Intern_String name){
AST_Node *node = ast_node_new(p, AK_Enum, token, name);
return node;
}
function AST_Node *
ast_struct(Parser *p, Token *token, Intern_String name, AST_Kind kind){
AST_Node *node = ast_node_new(p, kind, token, name);
return node;
}
function AST_Node *
ast_variable(Parser *p, Token *token, Intern_String name, AST_Node *type, Expr *expr){
AST_Node *node = ast_node_new(p, AK_Variable, token, name);
node->variable_type = type;
node->expr = expr;
return node;
}
function AST_Node *
ast_typedef(Parser *p, Token *token, Intern_String name, AST_Node *type){
AST_Node *node = ast_node_new(p, AK_Typedef, token, name);
node->typedef_type = type;
return node;
}
function AST_Node *
ast_function(Parser *p, Token *token, Intern_String name, AST_Node *return_type){
AST_Node *node = ast_node_new(p, AK_Function, token, name);
node->func_return_type = return_type;
return node;
}
function AST_Node *
ast_enum_child(Parser *p, Token *token, Intern_String name, Expr *expr){
AST_Node *node = ast_node_new(p, AK_EnumChild, token, name);
@@ -28,6 +63,39 @@ ast_enum_child(Parser *p, Token *token, Intern_String name, Expr *expr){
return node;
}
function void
ast_copy_symbol(AST_Node *dst, AST_Node *src){
AST_Node *scope_next = dst->next_scope;
*dst = *src;
dst->next_scope = scope_next;
}
function AST_Node *
ast_type_pointer(Parser *p, Token *token, AST_Node *pointer_to){
AST_Node *node = ast_node_new(p, AK_Pointer, token, intern_empty);
node->pointer = pointer_to;
return node;
}
function AST_Node *
ast_type_array(Parser *p, Token *token, AST_Node *pointer_to, Expr *expr){
AST_Node *node = ast_node_new(p, AK_Array, token, intern_empty);
node->pointer = pointer_to;
node->expr = expr;
return node;
}
function void
ast_node_pass_note_list(AST_Node *node, AST_Node *notes){
node->first_note = notes->first_note;
node->last_note = notes->last_note;
}
function void
ast_node_push_note(AST_Node *node, AST_Node *child){
SLLQueuePush(node->first_note, node->last_note, child);
}
function void
ast_node_push_child(AST_Node *node, AST_Node *child){
SLLQueuePush(node->first_child, node->last_child, child);

141
ast.h
View File

@@ -1,9 +1,142 @@
#if 0
String:struct{
str: U8*;
len: S64;
}
Intern_String:typedef String;
Token_Kind:enum{
@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,
}
Token:struct{
kind:Token_Kind;
union:{
string:String;
struct:{str:U8*; len:U64;}
}
union:{
int_val:S64;
error_val:String;
intern_val:Intern_String;
}
file:String;
line:S64;
line_begin:U8*;
}
AST_Kind:enum{
BaseType,
Typedef,
Enum,
Struct,
Union,
Note,
List,
Pointer,
Array,
Function,
Variable,
EnumChild,
}
AST_Node:struct{
kind: AST_Kind;
node: AST_Node[16];
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*;
}
}
#endif
typedef struct AST_Node AST_Node;
typedef struct Expr Expr;
typedef enum AST_Kind{
AK_None,
AK_Undefined,
AK_BaseType,
AK_Typedef,
@@ -19,7 +152,6 @@ typedef enum AST_Kind{
AK_Function,
AK_Variable,
AK_EnumChild,
}AST_Kind;
struct AST_Node{
@@ -29,7 +161,7 @@ struct AST_Node{
Intern_String name;
AST_Node *next;
AST_Node *scope_next;
AST_Node *next_scope;
AST_Node *first_note;
AST_Node *last_note;
@@ -37,9 +169,10 @@ struct AST_Node{
AST_Node *first_child;
AST_Node *last_child;
union{
AST_Node *pointer;
SizeU base_type_size;
AST_Node *pointer;
AST_Node *typedef_type;
AST_Node *variable_type;
AST_Node *func_return_type;
};
};

View File

@@ -1,3 +1,56 @@
call:(param:U32)U32{
}
@stringify
Enumeration:enum{
None,
Thing = 1 << 10,
Thing2,
Thing3,
}
@sllqueue()
@sllqueue(prefix=thing_scope, next=next_scope)
Thing:struct{
next: Thing*;
first: Thing*;
last: Thing*;
next_scope: Thing*;
val: U32[16];
str: String;
embed: struct{
thing: S32;
}
}
@register(sllqueue, first, last, next)
sllqueue_push:(base:T1, child:T2) void {
if(base.first == 0){
base.first = base.last = child;
}
else{
base.last = base.last.next = child;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
/*
function void
thing_sllqueue_push(){
}
function void
thing_scope_sllqueue_push(){
}
*/
Builtin types:
B8,B16,B32,B64
S8,S16,S32,S64
@@ -42,3 +95,5 @@ return 0;
if(a){}elseif(b){}else{}

4
lang.h
View File

@@ -41,7 +41,7 @@ typedef struct String{
S64 len;
}String;
#define SLLQueuePush(f,l,n) do{\
#define SLLQueuePushMod(f,l,n,next) do{\
if((f)==0){\
(f)=(l)=(n);\
}\
@@ -50,6 +50,8 @@ else{\
} \
}while(0)
#define SLLQueuePush(f,l,n) SLLQueuePushMod(f,l,n,next)
#define SLLStackPush(l,n) do{\
(n)->next = (l);\

41
lex.c
View File

@@ -57,7 +57,7 @@ lex_is_alphanumeric(U8 c){
function void
lex_set_len(Lex_Stream *s, Token *token){
assert(s->stream > token->str);
assert(s->stream >= token->str);
token->len = s->stream - token->str;
}
@@ -150,6 +150,13 @@ break
Token *t = token_alloc(tokens);
if(0){
top:
while(lex_is_whitespace(*s->stream))
lex_advance(s);
if(lexc(s) == 0)
break;
}
lex_token_seed(s, t);
lex_advance(s);
switch(*t->str) {
@@ -164,6 +171,7 @@ break
#undef CASE2
#undef CASE3
case 0: break;
case '@': t->kind = TK_At; break;
case '(': t->kind = TK_OpenParen; break;
case ')': t->kind = TK_CloseParen; break;
@@ -279,20 +287,21 @@ break
lex_advance(s);
if(lexc(s) == '/'){
lex_advance(s);
t->kind = TK_DocComment;
//t->kind = TK_DocComment;
}
else {
t->kind = TK_Comment;
//t->kind = TK_Comment;
}
for(;;){
if(lexc(s) == '\n' || lexc(s) == 0) break;
lex_advance(s);
}
lex_set_len(s,t);
goto top;
//lex_set_len(s,t);
}
else if(lexc(s) == '*'){
lex_advance(s);
t->kind = TK_Comment;
//t->kind = TK_Comment;
for(;;){
if(s->stream[0] == '*' && s->stream[1] == '/'){
lex_advance(s);
@@ -305,7 +314,8 @@ break
}
lex_advance(s);
}
lex_set_len(s,t);
goto top;
//lex_set_len(s,t);
}
else t->kind = TK_Div;
} break;
@@ -352,7 +362,7 @@ break
lex_advance(s);
lex_set_len(s,t);
} break;
default: {
default:{
token_error(t, lit("Unknown token"));
} break;
}
@@ -424,9 +434,7 @@ token_is_keyword(Parser *p, Intern_String keyword){
function void
token_advance(Parser *p){
do{
p->tokens.iter = clamp_top_s64(p->tokens.iter + 1, p->tokens.len);
}while(token_is_comment(token_get(p)));
p->tokens.iter = clamp_top_s64(p->tokens.iter + 1, p->tokens.len);
}
function Token *
@@ -495,4 +503,15 @@ token_peek_is(Parser *p, S64 count, Token_Kind kind){
if(token->kind == kind)
return token;
return 0;
}
}
function Token *
token_peek_is_keyword(Parser *p, S64 count, Intern_String keyword){
Token *token = token_peek(p, count);
if(token->kind == TK_Keyword){
if(intern_compare(keyword, token->intern_val)){
return token;
}
}
return 0;
}

30
main.c
View File

@@ -67,10 +67,10 @@ parser_test(){
}
parser_lex_stream(&p, lit("S64 thing; S64 second_var = 10;"), lit("File"));
assert(token_match(&p, TK_Keyword));
assert(token_match(&p, TK_Identifier));
assert(token_match(&p, TK_Identifier));
assert(token_match(&p, TK_Semicolon));
assert(token_match(&p, TK_Keyword));
assert(token_match(&p, TK_Identifier));
assert(token_match(&p, TK_Identifier));
assert(token_match(&p, TK_Assign));
assert(token_match(&p, TK_Int));
@@ -99,20 +99,26 @@ parser_test(){
lex_print("\n");
}
String decls[] = {
lit("enum Thing{ Thing_1 = 10, Thing_2 = 20<<1 };"),
};
for(S64 i = 0; i < buff_cap(decls); i++){
parser_lex_stream(&p, decls[i], lit("File"));
AST_Node *node = parse(&p);
assert(node);
}
/*
String decls =
lit("@Test(a=\"thing\") @str=\"based\" Thing:enum{ Thing_1 = 1<<10, Thing_2 = 10 }"
"TTT:struct{ thing:U64; nested:struct{ thing:S64; }}"
""
);
*/
String decls = os_read_file(lit("ast.h"));
parser_lex_stream(&p, decls, lit("File"));
AST_Node *node = parse(&p);
assert(node->first_child);
assert(node->last_child);
ast_print(node);
}
function S32
os_main(){
global_output_file = fopen("output.txt", "w");
global_output_file = fopen("output.cc", "w");
assert_msg(global_output_file, "Failed to open output.txt");
lex_test();
parser_test();

View File

@@ -24,8 +24,8 @@ arena_init(Arena *a){
function void *
arena_push_size(Arena *a, SizeU size){
SizeU generous_size = size + a->alignment;
if(generous_size>a->memory.commit){
SizeU generous_size = size;
if(a->memory.commit+generous_size>a->memory.commit){
if(a->memory.reserve == 0){
arena_init(a);
}

View File

@@ -22,6 +22,22 @@ WinMain(HINSTANCE hInstance, HINSTANCE a, LPSTR b, int nShowCmd){
return os_main();
}
function String
os_read_file(String name){
String result = {};
FILE *f = fopen((char *)name.str, "rb");
fseek(f, 0, SEEK_END);
result.len = ftell(f);
fseek(f, 0, SEEK_SET); /* same as rewind(f); */
result.str = malloc(result.len + 1);
fread(result.str, result.len, 1, f);
fclose(f);
result.str[result.len] = 0;
return result;
}
function OS_Memory
os_reserve(SizeU size){
OS_Memory result = {0};

142
output.cc Normal file
View File

@@ -0,0 +1,142 @@
(4+(2*53))
Error: Expected token of kind: ), got instead token of kind: End of stream
((4+2)*53)
(++5)
(--5)
(-5)
(+5)
(()5)
((()5)+3)
((534>43)?435:42)
(((534>43)?435:42),234,(()42),Thing[10][2],Thing(1,2))
typedef struct String String;
struct String{
U8 *str;
S64 len;
};
typedef Intern_String;
enum Token_Kind{
End,
Mul,
Div,
Add,
Sub,
Mod,
BitAnd,
BitOr,
BitXor,
Neg,
Not,
OpenParen,
CloseParen,
OpenBrace,
CloseBrace,
OpenBracket,
CloseBracket,
Comma,
Pound,
Question,
ThreeDots,
Semicolon,
Dot,
LesserThen,
GreaterThen,
Colon,
Assign,
DivAssign,
MulAssign,
ModAssign,
SubAssign,
AddAssign,
AndAssign,
OrAssign,
XorAssign,
LeftShiftAssign,
RightShiftAssign,
DoubleColon,
At,
Decrement,
Increment,
PostDecrement,
PostIncrement,
LesserThenOrEqual,
GreaterThenOrEqual,
Equals,
And,
Or,
NotEquals,
LeftShift,
RightShift,
Arrow,
ExprSizeof,
DocComment,
Comment,
Identifier,
StringLit,
U8Lit,
Character,
Error,
Float,
Int,
Keyword,
}
typedef struct Token Token;
struct Token{
Token_Kind kind;
union {
String string;
struct {
U8 *str;
U64 len;
};
};
union {
S64 int_val;
String error_val;
String intern_val;
};
String file;
S64 line;
U8 *line_begin;
};
enum AST_Kind{
BaseType,
Typedef,
Enum,
Struct,
Union,
Note,
List,
Pointer,
Array,
Function,
Variable,
EnumChild,
}
typedef struct AST_Node AST_Node;
struct AST_Node{
AST_Kind kind;
AST_Node node[16];
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;
};
};

View File

@@ -1,50 +1,168 @@
global Intern_String intern_empty;
function Token *
parse__get_name(Parser *p){
Token *name = token_next(p);
token_next(p);
token_next(p);
return name;
}
function void
parse_note_list(Parser *ctx, AST_Node *parent) {
if(token_match(ctx, TK_OpenParen)) {
do {
Token *name = token_expect(ctx, TK_Identifier);
AST_Node *current = ast_note(ctx, name, name->intern_val, 0);
ast_node_push_note(parent, current);
parse_note_list(ctx, current);
if(token_match(ctx, TK_Assign)) {
current->expr = parse_expr(ctx);
}
} while(token_match(ctx, TK_Comma));
token_expect(ctx, TK_CloseParen);
}
}
function void
parse__notes(Parser *ctx, AST_Node *result) {
while(token_match(ctx, TK_At)) {
Token *name = token_expect(ctx, TK_Identifier);
AST_Node *current = ast_note(ctx, name, name->intern_val, 0);
ast_node_push_note(result, current);
parse_note_list(ctx, current);
if(token_match(ctx, TK_Assign)) {
current->expr = parse_expr(ctx);
}
}
}
function AST_Node
parse_notes(Parser *p){
AST_Node result = {};
parse__notes(p, &result);
return result;
}
function AST_Node *
parse_enum(Parser *p){
parse_enum(Parser *p, Token *name){
AST_Node *result = 0;
Token *name = token_match(p, TK_Identifier);
if(token_match(p, TK_OpenBrace)){
Token *op_close_brace = token_match(p, TK_CloseBrace);
if(!op_close_brace){
result = ast_enum(p, name, name->intern_val);
do{ // Parse enum members
Token *identifier = token_match(p, TK_Identifier);
if(identifier){
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
AST_Node *child = ast_enum_child(p, identifier, identifier->intern_val, expr);
ast_node_push_child(result, child);
{
// Insert into scope
}
if(token_expect(p, TK_OpenBrace)){
result = ast_enum(p, name, name->intern_val);
do{
AST_Node notes = parse_notes(p);
Token *token = token_match(p, TK_Identifier);
if(token){
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
else {
parser_push_error(p, token_get(p), "invalid syntax of enum member");
AST_Node *child = ast_enum_child(p, token, token->intern_val, expr);
ast_node_pass_note_list(child,&notes);
ast_node_push_child(result, child);
}
else{
break;
}
} while(token_match(p, TK_Comma));
token_expect(p, TK_CloseBrace);
}
return result;
}
function AST_Node *
parse_variable(Parser *p, Token *name){
AST_Node *result = 0;
Token *type_token = token_expect(p, TK_Identifier);
if(type_token){
AST_Node *type = symbol_require_type(p, type_token);
Token *star;
while((star = token_match(p, TK_Mul))){
type = ast_type_pointer(p, star, type);
}
while((star = token_match(p, TK_OpenBracket))){
Expr *expr = parse_expr(p);
type = ast_type_array(p, star, type, expr);
token_expect(p, TK_CloseBracket);
}
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
result = ast_variable(p, name, name->intern_val, type, expr);
}
return result;
}
function AST_Node *
parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){
AST_Node *result = 0;
if(token_expect(p, TK_OpenBrace)){
result = ast_struct(p, name, name?name->intern_val:(Intern_String){}, kind);
if(is_global) symbol_register(p, result);
for(;;){
AST_Node notes = parse_notes(p);
AST_Node *mem = 0;
Token *mem_name = token_match(p, TK_Identifier);
if(mem_name){
if(token_expect(p, TK_Colon)){
if(token_match_keyword(p, keyword_struct)){
mem = parse_struct(p, mem_name, AK_Struct, false);
}
else if(token_match_keyword(p, keyword_union)){
mem = parse_struct(p, mem_name, AK_Union, false);
}
//else if(token_match_keyword(p, keyword_enum)){
//mem = parse_enum(p, mem_name);
//}
else if(token_is(p, TK_Identifier)){
mem = parse_variable(p, mem_name);
token_expect(p, TK_Semicolon);
}
else parser_push_error(p, mem_name, "Unrecognized token while parsing struct");
if(mem){
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
}
else{
break;
}
} while(token_match(p, TK_Comma));
token_expect(p, TK_CloseBrace);
}
else{
parser_push_error(p, op_close_brace, "enum without body");
}
else if(token_match_keyword(p, keyword_union) &&
token_match(p, TK_Colon)){
mem = parse_struct(p, 0, AK_Union, false);
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
else if(token_match_keyword(p, keyword_struct) &&
token_match(p, TK_Colon)){
mem = parse_struct(p, 0, AK_Struct, false);
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
else if(token_expect(p, TK_CloseBrace)){
break;
}
else{
break;
}
}
}
else{
if(name == 0){
parser_push_error(p, token_get(p), "enum without name or body is illegal");
}
}
if(ast_is_named(result)){
// Insert into scope
}
return result;
}
function AST_Node *
parse_typedef(Parser *p, Token *name){
Token *type_token = token_expect(p, TK_Identifier);
AST_Node *type = symbol_require_type(p, type_token);
AST_Node *result = ast_typedef(p, name, name->intern_val, type);
token_expect(p, TK_Semicolon);
return result;
}
@@ -54,6 +172,7 @@ parse(Parser *p){
for(;;){
AST_Node *node = 0;
AST_Node notes = parse_notes(p);
if(token_is(p, TK_End)){
break;
@@ -61,29 +180,40 @@ parse(Parser *p){
else if(token_is(p, TK_Error)){
break;
}
else if(token_match_keyword(p, keyword_struct)){
else if(token_is(p, TK_Identifier) && // Peeking to be more error averse
token_peek_is(p, 1, TK_Colon)){
if(token_peek_is_keyword(p, 2, keyword_struct)){
node = parse_struct(p, parse__get_name(p), AK_Struct, true);
symbol_register(p, node);
}
else if(token_peek_is_keyword(p, 2, keyword_union)){
node = parse_struct(p, parse__get_name(p), AK_Union, true);
symbol_register(p, node);
}
else if(token_peek_is_keyword(p, 2, keyword_enum)){
node = parse_enum(p, parse__get_name(p));
symbol_register(p, node);
}
else if(token_peek_is_keyword(p, 2, keyword_typedef)){
node = parse_typedef(p, parse__get_name(p));
symbol_register(p, node);
}
else{
token_next(p);
}
}
else if(token_match_keyword(p, keyword_union)){
}
else if(token_match_keyword(p, keyword_enum)){
node = parse_enum(p);
token_expect(p, TK_Semicolon);
}
else if(token_match_keyword(p, keyword_function)){
}
else if(token_match_keyword(p, keyword_typedef)){
}
else {
else{
token_next(p);
}
if(node){
ast_node_pass_note_list(node, &notes);
ast_node_push_child(result, node);
}
else if(notes.first_note != 0){
parser_push_error(p, token_get(p), "Warning: notes got lost");
}
}
return result;

View File

@@ -92,7 +92,7 @@ Expr* parse_unary_expr(Parser* p) {
}
else if (token_is(p, TK_OpenParen)) { // cast requires lookahead
Token *token = token_peek(p, 1);
if (token->kind == TK_Keyword || token->kind == TK_Identifier) {
if (token->kind == TK_Identifier) {
AST_Node *type = symbol_lookup_type(p, token->intern_val);
if(type){

138
parser.c
View File

@@ -1,9 +1,19 @@
global Intern_String keyword_s64;
global Intern_String keyword_u64;
global Intern_String keyword_void;
global Intern_String keyword_sizeu;
global Intern_String keyword_sizeof;
global Intern_String intern_empty;
global Intern_String intern_s64;
global Intern_String intern_s32;
global Intern_String intern_s16;
global Intern_String intern_s8;
global Intern_String intern_u64;
global Intern_String intern_u32;
global Intern_String intern_u16;
global Intern_String intern_u8;
global Intern_String intern_void;
global Intern_String intern_sizeu;
global Intern_String keyword_sizeof;
global Intern_String keyword_enum;
global Intern_String keyword_typedef;
global Intern_String keyword_struct;
@@ -12,7 +22,15 @@ global Intern_String keyword_function;
global Intern_String keyword_global;
global AST_Node *type_s64;
global AST_Node *type_s32;
global AST_Node *type_s16;
global AST_Node *type_s8;
global AST_Node *type_u64;
global AST_Node *type_u32;
global AST_Node *type_u16;
global AST_Node *type_u8;
global AST_Node *type_void;
global AST_Node *type_sizeu;
@@ -24,10 +42,6 @@ parser_init(Parser *p){
p->symbols_count = 4096;
p->symbols = arena_push_array(&p->symbol_table_arena, AST_Node, p->symbols_count);
keyword_s64 = intern_string(p, lit("S64"));
keyword_u64 = intern_string(p, lit("U64"));
keyword_void = intern_string(p, lit("void"));
keyword_sizeu = intern_string(p, lit("SizeU"));
keyword_sizeof = intern_string(p, lit("sizeof"));
keyword_struct = intern_string(p, lit("struct"));
keyword_enum = intern_string(p, lit("enum"));
@@ -35,14 +49,37 @@ parser_init(Parser *p){
keyword_union = intern_string(p, lit("union"));
keyword_function = intern_string(p, lit("function"));
keyword_global = intern_string(p, lit("global"));
p->first_keyword = keyword_s64.s.str;
p->first_keyword = keyword_sizeof.s.str;
p->last_keyword = keyword_global.s.str;
intern_s64 = intern_string(p, lit("S64"));
intern_s32 = intern_string(p, lit("S32"));
intern_s16 = intern_string(p, lit("S16"));
intern_s8 = intern_string(p, lit("S8"));
intern_u64 = intern_string(p, lit("U64"));
intern_u32 = intern_string(p, lit("U32"));
intern_u16 = intern_string(p, lit("U16"));
intern_u8 = intern_string(p, lit("U8"));
intern_void = intern_string(p, lit("void"));
intern_sizeu = intern_string(p, lit("SizeU"));
parser_push_scope(p); // Global scope
type_s64 = symbol_register_basic_type(p, keyword_s64, sizeof(S64));
type_u64 = symbol_register_basic_type(p, keyword_u64, sizeof(U64));
type_sizeu = symbol_register_basic_type(p, keyword_sizeu, sizeof(SizeU));
type_void = symbol_register_basic_type(p, keyword_void, sizeof(void));
type_s64 = symbol_register_basic_type(p, intern_s64, sizeof(S64));
type_s32 = symbol_register_basic_type(p, intern_s32, sizeof(S32));
type_s16 = symbol_register_basic_type(p, intern_s16, sizeof(S16));
type_s8 = symbol_register_basic_type(p, intern_s8, sizeof(S8));
type_u64 = symbol_register_basic_type(p, intern_u64, sizeof(U64));
type_u32 = symbol_register_basic_type(p, intern_u32, sizeof(U32));
type_u16 = symbol_register_basic_type(p, intern_u16, sizeof(U16));
type_u8 = symbol_register_basic_type(p, intern_u8, sizeof(U8));
type_void = symbol_register_basic_type(p, intern_void, sizeof(void));
type_sizeu = symbol_register_basic_type(p, intern_sizeu, sizeof(SizeU));
}
@@ -53,19 +90,6 @@ intern_is_keyword(Parser *p, Intern_String intern){
return false;
}
function void
intern_tokens(Parser *p){
for(S64 i = 0; i < p->tokens.len; i++){
Token *t = p->tokens.tokens + i;
if(t->kind == TK_Identifier){
t->intern_val = intern_string(p, t->string);
if(intern_is_keyword(p, t->intern_val)){
t->kind = TK_Keyword;
}
}
}
}
function void
parser_push_error(Parser *p, Token *token, char *str, ...){
@@ -90,6 +114,22 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
SLLQueuePush(p->first_error, p->last_error, error);
}
function void
intern_tokens(Parser *p){
for(S64 i = 0; i < p->tokens.len; i++){
Token *t = p->tokens.tokens + i;
if(t->kind == TK_Identifier){
t->intern_val = intern_string(p, t->string);
if(intern_is_keyword(p, t->intern_val)){
t->kind = TK_Keyword;
}
}
else if(t->kind == TK_Error){
parser_push_error(p, t, (char *)t->error_val.str);
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
@@ -162,10 +202,10 @@ symbol_alloc_slot(Parser *p, Intern_String string, B32 is_global){
if(symbol->name.s.str == 0){
/* @Note(Krzosa): Push on scope */ {
if(is_global){
SLLQueuePush(p->scope_stack->first, p->scope_stack->last, symbol);
SLLQueuePushMod(p->scope_stack->first, p->scope_stack->last, symbol, next_scope);
}
else{
SLLQueuePush(p->global_scope->first, p->global_scope->last, symbol);
SLLQueuePushMod(p->global_scope->first, p->global_scope->last, symbol, next_scope);
}
}
symbol->name = string;
@@ -181,6 +221,7 @@ symbol_alloc_slot(Parser *p, Intern_String string, B32 is_global){
break;
}
assert_msg(0, "Ran out of slots in symbol table");
return 0;
}
@@ -205,11 +246,39 @@ symbol_lookup(Parser *p, Intern_String string){
function AST_Node *
symbol_register_basic_type(Parser *p, Intern_String string, SizeU size){
AST_Node *node = symbol_alloc_slot(p, string, true);
assert(node->kind == AK_None);
node->kind = AK_BaseType;
node->base_type_size = size;
return node;
}
function void
symbol_register(Parser *p, AST_Node *node){
AST_Node *look = symbol_alloc_slot(p, node->name, false);
if(look->kind == AK_None){
ast_copy_symbol(look, node);
}
else if(look->kind == node->kind){
if(look->kind == AK_Enum ||
look->kind == AK_Function ||
look->kind == AK_Union ||
look->kind == AK_Struct){
if(look->first_child == 0){
ast_copy_symbol(look, node);
}
else {
parser_push_error(p, token_get(p), "Symbol already has a body");
}
}
else {
parser_push_error(p, token_get(p), "Trying to register a symbol again");
}
}
else{
parser_push_error(p, token_get(p), "Trying to register a symbol of different kind with the same name");
}
}
function AST_Node *
symbol_lookup_type(Parser *p, Intern_String string){
AST_Node *node = symbol_lookup(p, string);
@@ -221,6 +290,15 @@ symbol_lookup_type(Parser *p, Intern_String string){
return 0;
}
function AST_Node *
symbol_require_type(Parser *p, Token *token){
AST_Node *result = symbol_lookup_type(p, token->intern_val);
if(!result){
parser_push_error(p, token, "Undefined type");
}
return result;
}
function void
parser_push_scope(Parser *p){
Scope *scope = 0;
@@ -240,7 +318,7 @@ parser_pop_scope(Parser *p){
SLLStackPop(p->scope_stack, scope);
assert(scope);
for(AST_Node *s = scope->first; s; s=s->scope_next){
for(AST_Node *s = scope->first; s; s=s->next_scope){
memory_zero(s, sizeof(AST_Node));
p->symbols_inserted--;
}

View File

@@ -48,3 +48,4 @@ function Token *token_get(Parser *p);
function B32 intern_compare(Intern_String a, Intern_String b);
function void parser_push_scope(Parser *p);
function AST_Node *symbol_register_basic_type(Parser *p, Intern_String string, SizeU size);
function void ast_copy_symbol(AST_Node *dst, AST_Node *src);

137
print.c
View File

@@ -74,3 +74,140 @@ expr_print(Expr *expr){
default: {invalid_codepath;} break;
}
}
function void
print_indent(S64 indent){
for(S64 i = 0; i < indent; i++){
lex_print(" ");
}
}
function AST_Node *
ast_get_basis_type(AST_Node *node){
switch(node->kind) {
case AK_Struct: case AK_Union: case AK_Enum: case AK_BaseType:{return node;} break;
case AK_Function:{return node;} break;
case AK_Typedef:{return node->typedef_type;} break;
case AK_Array: case AK_Pointer:{return ast_get_basis_type(node->pointer);} break;
default: invalid_codepath;
}
return 0;
}
function void
ast_print_pointers(AST_Node *node){
if(node->kind == AK_Pointer){
lex_print("*");
ast_print_pointers(node->pointer);
}
else if(node->kind == AK_Array){
ast_print_pointers(node->pointer);
}
}
function void
ast_print_arrays(AST_Node *node){
if(node->kind == AK_Pointer){
ast_print_arrays(node->pointer);
}
else if(node->kind == AK_Array){
lex_print("[");
expr_print(node->expr);
lex_print("]");
ast_print_arrays(node->pointer);
}
}
function void
ast_print_var(AST_Node *node);
function void
ast_print_func_params(AST_Node *node){
for(AST_Node *n = node->first_child; n; n=n->next){
ast_print_var(n);
if(n != node->last_child) lex_print(", ");
}
}
function void
ast_print_var(AST_Node *node){
AST_Node *basis_type = ast_get_basis_type(node->variable_type);
if(basis_type->kind == AK_Function){
lex_print("%s (*%s)(", basis_type->func_return_type->name.s.str, node->name.s.str);
ast_print_func_params(basis_type);
lex_print(")");
}
else{
lex_print("%s ", basis_type->name.s.str);
ast_print_pointers(node->variable_type);
lex_print("%s", node->name.s.str);
ast_print_arrays(node->variable_type);
}
if(node->expr){
lex_print(" = ");
expr_print(node->expr);
}
}
function void
ast__print(AST_Node *node, S64 indent){
switch(node->kind){
case AK_List:{
for(AST_Node *n = node->first_child; n; n=n->next){
ast__print(n, indent);
lex_print("\n");
}
} break;
case AK_Union:
case AK_Struct:{
const char *type = node->kind == AK_Struct ? "struct":"union";
if(indent == 0) lex_print("typedef %s %s %s;\n", type, node->name.s.str, node->name.s.str);
lex_print("%s %s{\n", type, indent == 0 ? node->name.s.str:(U8 *)"");
for(AST_Node *n = node->first_child; n; n=n->next){
ast__print(n, indent+2);
lex_print("\n");
}
lex_print("}");
lex_print("%s;\n", indent == 0 ? (U8 *)"":node->name.s.str?node->name.s.str:(U8*)"");
} break;
case AK_Variable:{
if(indent == 0) lex_print("global ");
ast_print_var(node);
lex_print(";");
} break;
case AK_Typedef:{
lex_print("typedef ");
lex_print("%s;", node->name.s.str);
} break;
case AK_Enum:{
print_indent(indent);
lex_print("enum %s{\n", node->name.s.str);
for(AST_Node *n = node->first_child; n; n=n->next){
print_indent(indent+2);
lex_print("%s", n->name.s.str);
if(n->expr){
lex_print(" = ");
expr_print(n->expr);
}
lex_print(",\n");
}
print_indent(indent);
lex_print("}\n");
} break;
default: invalid_codepath;
}
}
function void
ast_print(AST_Node *node){
ast__print(node, 0);
}