New syntax that's easier to parse, parsing doesn't need variable lookup
This commit is contained in:
127
ast.c
Normal file
127
ast.c
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
|
||||||
|
function Decl *
|
||||||
|
decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
|
||||||
|
Decl *result = arena_push_struct(&p->main_arena, Decl);
|
||||||
|
result->kind = kind;
|
||||||
|
result->pos = pos;
|
||||||
|
result->name = name;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Decl *
|
||||||
|
decl_struct(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
|
||||||
|
assert(kind == DECL_Struct || kind == DECL_Union);
|
||||||
|
Decl *result = decl_new(p, kind, pos, name);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Decl *
|
||||||
|
decl_typedef(Parser *p, Token *pos, Intern_String name, Typespec *type){
|
||||||
|
Decl *result = decl_new(p, DECL_Typedef, pos, name);
|
||||||
|
result->typedef_decl.type = type;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Decl *
|
||||||
|
decl_enum(Parser *p, Token *pos, Intern_String name, Typespec *typespec){
|
||||||
|
Decl *result = decl_new(p, DECL_Enum, pos, name);
|
||||||
|
result->enum_decl.typespec = typespec;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Decl *
|
||||||
|
decl_variable(Parser *p, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){
|
||||||
|
Decl *result = decl_new(p, DECL_Variable, pos, name);
|
||||||
|
result->variable_decl.type = typespec;
|
||||||
|
result->variable_decl.expr = expr;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
decl_enum_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){
|
||||||
|
assert(parent->kind == DECL_Enum);
|
||||||
|
Decl_Enum_Child *child = arena_push_struct(&p->main_arena, Decl_Enum_Child);
|
||||||
|
child->pos = pos;
|
||||||
|
child->name = name;
|
||||||
|
child->expr = expr;
|
||||||
|
child->first_note = notes->first;
|
||||||
|
child->last_note = notes->last;
|
||||||
|
SLLQueuePush(parent->enum_decl.first, parent->enum_decl.last, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
decl_struct_push(Decl *parent, Decl *child){
|
||||||
|
assert(parent->kind == DECL_Struct || parent->kind == DECL_Union);
|
||||||
|
SLLQueuePush(parent->struct_decl.first, parent->struct_decl.last, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
decl_list_push(Decl *parent, Decl *child){
|
||||||
|
assert(parent->kind == DECL_List);
|
||||||
|
SLLQueuePush(parent->list.first, parent->list.last, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
result->pos = pos;
|
||||||
|
result->name = name;
|
||||||
|
result->expr = expr;
|
||||||
|
SLLQueuePush(parent->first, parent->last, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
decl_pass_notes(Decl *a, Note *b){
|
||||||
|
a->first_note = b->first;
|
||||||
|
a->last_note = b->last;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Typespec *
|
||||||
|
typespec_new(Parser *p, Typespec_Kind kind, Token *pos){
|
||||||
|
Typespec *result = arena_push_struct(&p->main_arena, Typespec);
|
||||||
|
result->kind = kind;
|
||||||
|
result->pos = 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);
|
||||||
|
result->name = name;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Typespec *
|
||||||
|
typespec_pointer(Parser *p, Token *pos, Typespec *base){
|
||||||
|
Typespec *result = typespec_new(p, TS_Pointer, pos);
|
||||||
|
result->base = base;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Typespec *
|
||||||
|
typespec_array(Parser *p, Token *pos, Typespec *base, Expr *size){
|
||||||
|
Typespec *result = typespec_new(p, TS_Array, pos);
|
||||||
|
result->array_spec.base = base;
|
||||||
|
result->array_spec.size = size;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Typespec *
|
||||||
|
typespec_function(Parser *p, Token *pos, Typespec *ret){
|
||||||
|
Typespec *result = typespec_new(p, TS_Function, pos);
|
||||||
|
result->function_spec.ret = ret;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
typespec_function_push(Typespec *func, Typespec *arg){
|
||||||
|
SLLQueuePush(func->function_spec.first, func->function_spec.last, arg);
|
||||||
|
}
|
||||||
106
ast.h
Normal file
106
ast.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
typedef struct Decl_Enum_Child Decl_Enum_Child;
|
||||||
|
typedef struct Typespec Typespec;
|
||||||
|
typedef struct Decl Decl;
|
||||||
|
typedef struct Note Note;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Type specifier
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
typedef enum Typespec_Kind{
|
||||||
|
TS_None,
|
||||||
|
TS_Name,
|
||||||
|
TS_Pointer,
|
||||||
|
TS_Array,
|
||||||
|
TS_Function,
|
||||||
|
TS_Struct,
|
||||||
|
}Typespec_Kind;
|
||||||
|
|
||||||
|
struct Typespec{
|
||||||
|
Typespec_Kind kind;
|
||||||
|
Typespec *next;
|
||||||
|
Token *pos;
|
||||||
|
union{
|
||||||
|
Intern_String name;
|
||||||
|
Decl *struct_spec;
|
||||||
|
struct{
|
||||||
|
Typespec *first;
|
||||||
|
Typespec *last;
|
||||||
|
Typespec *ret;
|
||||||
|
}function_spec;
|
||||||
|
struct{
|
||||||
|
Typespec *base;
|
||||||
|
Expr *size;
|
||||||
|
}array_spec;
|
||||||
|
Typespec *base;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Notes
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct Note{
|
||||||
|
Token *pos;
|
||||||
|
Intern_String name;
|
||||||
|
Expr *expr;
|
||||||
|
|
||||||
|
Note *next;
|
||||||
|
Note *first;
|
||||||
|
Note *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Declarations
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
typedef enum Decl_Kind{
|
||||||
|
DECL_None,
|
||||||
|
DECL_Struct,
|
||||||
|
DECL_Union,
|
||||||
|
DECL_Enum,
|
||||||
|
DECL_Variable,
|
||||||
|
DECL_Typedef,
|
||||||
|
DECL_List,
|
||||||
|
}Decl_Kind;
|
||||||
|
|
||||||
|
struct Decl_Enum_Child{
|
||||||
|
Decl_Enum_Child *next;
|
||||||
|
Intern_String name;
|
||||||
|
Token *pos;
|
||||||
|
Expr *expr;
|
||||||
|
|
||||||
|
Note *first_note;
|
||||||
|
Note *last_note;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Decl{
|
||||||
|
Decl_Kind kind;
|
||||||
|
Intern_String name;
|
||||||
|
Token *pos;
|
||||||
|
Decl *next;
|
||||||
|
|
||||||
|
Note *first_note;
|
||||||
|
Note *last_note;
|
||||||
|
|
||||||
|
union{
|
||||||
|
struct{
|
||||||
|
Decl_Enum_Child *first;
|
||||||
|
Decl_Enum_Child *last;
|
||||||
|
Typespec *typespec;
|
||||||
|
}enum_decl;
|
||||||
|
struct{
|
||||||
|
Decl *first;
|
||||||
|
Decl *last;
|
||||||
|
} struct_decl;
|
||||||
|
struct{
|
||||||
|
Typespec *type;
|
||||||
|
Expr *expr;
|
||||||
|
}variable_decl;
|
||||||
|
struct{
|
||||||
|
Typespec *type;
|
||||||
|
}typedef_decl;
|
||||||
|
struct{
|
||||||
|
Decl *first;
|
||||||
|
Decl *last;
|
||||||
|
}list;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
20
expr.c
20
expr.c
@@ -53,15 +53,29 @@ expr_index(Parser *p, Token *token, Expr *atom, Expr *index){
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
function Expr *
|
function Expr *
|
||||||
expr_cast(Parser *p, Token *token, AST_Node *type, Expr *exp){
|
expr_cast(Parser *p, Token *token, Typespec *type, Expr *exp){
|
||||||
Expr *expr = expr_new(p, EK_Cast, token);
|
Expr *expr = expr_new(p, EK_Cast, token);
|
||||||
expr->cast.type = type;
|
expr->cast.type = type;
|
||||||
expr->cast.expr = exp;
|
expr->cast.expr = exp;
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
function Expr *
|
||||||
|
expr_sizeof_type(Parser *p, Token *token, Typespec *type){
|
||||||
|
Expr *expr = expr_new(p, EK_Sizeof, token);
|
||||||
|
expr->size_of.kind = SIZEOF_Type;
|
||||||
|
expr->size_of.type = type;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Expr *
|
||||||
|
expr_sizeof_expr(Parser *p, Token *token, Expr *in_expr){
|
||||||
|
Expr *expr = expr_new(p, EK_Sizeof, token);
|
||||||
|
expr->size_of.kind = SIZEOF_Expr;
|
||||||
|
expr->size_of.expr = in_expr;
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
function Expr *
|
function Expr *
|
||||||
expr_list(Parser *p, Token *token){
|
expr_list(Parser *p, Token *token){
|
||||||
|
|||||||
16
expr.h
16
expr.h
@@ -1,5 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
typedef struct Expr Expr;
|
typedef struct Expr Expr;
|
||||||
|
typedef struct Typespec Typespec;
|
||||||
|
|
||||||
|
typedef enum Expr_Sizeof_Kind{
|
||||||
|
SIZEOF_Expr,
|
||||||
|
SIZEOF_Type,
|
||||||
|
}Expr_Sizeof_Kind;
|
||||||
|
|
||||||
typedef enum Expr_Kind{
|
typedef enum Expr_Kind{
|
||||||
EK_None,
|
EK_None,
|
||||||
@@ -11,6 +17,7 @@ typedef enum Expr_Kind{
|
|||||||
EK_List,
|
EK_List,
|
||||||
EK_Call,
|
EK_Call,
|
||||||
EK_Index,
|
EK_Index,
|
||||||
|
EK_Sizeof,
|
||||||
} Expr_Kind;
|
} Expr_Kind;
|
||||||
|
|
||||||
struct Expr {
|
struct Expr {
|
||||||
@@ -19,7 +26,7 @@ struct Expr {
|
|||||||
Expr *next;
|
Expr *next;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
//Typespec *type;
|
Typespec *type;
|
||||||
Expr* expr;
|
Expr* expr;
|
||||||
} cast;
|
} cast;
|
||||||
struct {
|
struct {
|
||||||
@@ -46,5 +53,12 @@ struct Expr {
|
|||||||
Expr* on_true;
|
Expr* on_true;
|
||||||
Expr* on_false;
|
Expr* on_false;
|
||||||
} ternary;
|
} ternary;
|
||||||
|
struct{
|
||||||
|
Expr_Sizeof_Kind kind;
|
||||||
|
union{
|
||||||
|
Typespec *type;
|
||||||
|
Expr *expr;
|
||||||
|
};
|
||||||
|
} size_of;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
38
ideas.cpp
38
ideas.cpp
@@ -1,5 +1,41 @@
|
|||||||
|
Thing :: struct{
|
||||||
|
data: (U32) U32; // Function pointer
|
||||||
|
data: (U32) U32 @ [32]; // Array of function pointers
|
||||||
|
data: (U32) U32* @ [32]; // Array of function pointers, they return a pointer
|
||||||
|
|
||||||
Thingy::enum{
|
actual_function :: (first: Thing*, last: Thing*, node: Thing*)/*no type == void*/{
|
||||||
|
if first == 0 {
|
||||||
|
first = last = node;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
last = last->next = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StructInside :: struct { // This is not part of struct
|
||||||
|
// just in scope
|
||||||
|
some_val: U16;
|
||||||
|
some_val2: U16;
|
||||||
|
}
|
||||||
|
|
||||||
|
insider: StructInside;
|
||||||
|
|
||||||
|
named_union_part_of_struct: union{
|
||||||
|
some_val: U16;
|
||||||
|
some_val2: U32;
|
||||||
|
}
|
||||||
|
|
||||||
|
_: union {
|
||||||
|
// Unamed union
|
||||||
|
val: U32;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Thingy::enum:U32{
|
||||||
@str=10 Value = 1,
|
@str=10 Value = 1,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
24
main.c
24
main.c
@@ -9,6 +9,7 @@
|
|||||||
#include "lex.h"
|
#include "lex.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
#include "ast.h"
|
||||||
|
|
||||||
global FILE *global_output_file;
|
global FILE *global_output_file;
|
||||||
#define lex_print(...) fprintf(global_output_file, __VA_ARGS__)
|
#define lex_print(...) fprintf(global_output_file, __VA_ARGS__)
|
||||||
@@ -21,8 +22,10 @@ global FILE *global_output_file;
|
|||||||
|
|
||||||
#include "lex.c"
|
#include "lex.c"
|
||||||
#include "expr.c"
|
#include "expr.c"
|
||||||
|
#include "ast.c"
|
||||||
#include "parse_expr.c"
|
#include "parse_expr.c"
|
||||||
#include "parse_decl.c"
|
#include "parse_decl.c"
|
||||||
|
#include "print.c"
|
||||||
|
|
||||||
function void
|
function void
|
||||||
lex_test(){
|
lex_test(){
|
||||||
@@ -77,25 +80,40 @@ parser_test(){
|
|||||||
assert(token_match(&p, TK_End));
|
assert(token_match(&p, TK_End));
|
||||||
|
|
||||||
String exprs[] = {
|
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("((4+2)*53)"),
|
lit("((4+2)*53)"),
|
||||||
lit("++5"),
|
lit("++5"),
|
||||||
lit("5--"), // @Todo(Krzosa):
|
lit("5--"), // @Todo(Krzosa):
|
||||||
lit("-5"),
|
lit("-5"),
|
||||||
lit("(+5)"),
|
lit("(+5)"),
|
||||||
lit("cast(S64)5"),
|
lit("sizeof(32) + sizeof(:S32*)"),
|
||||||
|
lit("cast(S64**)5"),
|
||||||
lit("cast(S64)5+3"),
|
lit("cast(S64)5+3"),
|
||||||
lit("534>43?435:42"),
|
lit("534>43?435:42"),
|
||||||
lit("(534>43?435:42,234,cast(S64)42,Thing[10][2],Thing(1,2))"),
|
|
||||||
};
|
};
|
||||||
for(S64 i = 0; i < buff_cap(exprs); i++){
|
for(S64 i = 0; i < buff_cap(exprs); i++){
|
||||||
parser_lex_stream(&p, exprs[i], lit("File"));
|
parser_lex_stream(&p, exprs[i], lit("File"));
|
||||||
Expr *expr = parse_expr(&p);
|
Expr *expr = parse_expr(&p);
|
||||||
assert(expr);
|
assert(expr);
|
||||||
expr_print(expr);
|
expr_print(&p, expr);
|
||||||
lex_print("\n");
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
function S32
|
function S32
|
||||||
|
|||||||
246
output.cc
246
output.cc
@@ -0,0 +1,246 @@
|
|||||||
|
(((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)
|
||||||
|
struct OS_Memory{
|
||||||
|
data: void*;
|
||||||
|
commit: SizeU;
|
||||||
|
reserve: SizeU;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Arena{
|
||||||
|
@using memory: OS_Memory;
|
||||||
|
len: U64;
|
||||||
|
alignment: U64;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct String{
|
||||||
|
str: U8*;
|
||||||
|
len: S64;
|
||||||
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Token{
|
||||||
|
kind: Token_Kind;
|
||||||
|
@using string: String;
|
||||||
|
val: union {
|
||||||
|
integer: S64;
|
||||||
|
error: String;
|
||||||
|
intern: Intern_String;
|
||||||
|
};
|
||||||
|
|
||||||
|
file: String;
|
||||||
|
line: S64;
|
||||||
|
line_begin: U8*;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Tokens{
|
||||||
|
@array tokens: Token*;
|
||||||
|
iter: S64;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Lex_Stream{
|
||||||
|
stream: U8*;
|
||||||
|
line_begin: U8*;
|
||||||
|
filename: String;
|
||||||
|
line: S64;
|
||||||
|
};
|
||||||
|
|
||||||
|
@prefix = EK_ enum Expr_Kind : S64{
|
||||||
|
None,
|
||||||
|
Atom,
|
||||||
|
Unary,
|
||||||
|
Binary,
|
||||||
|
Ternary,
|
||||||
|
Cast,
|
||||||
|
List,
|
||||||
|
Call,
|
||||||
|
Index,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Expr{
|
||||||
|
kind: Expr_Kind;
|
||||||
|
token: Token*;
|
||||||
|
next: Expr*;
|
||||||
|
_: 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_ enum AST_Kind : S64{
|
||||||
|
None,
|
||||||
|
BaseType,
|
||||||
|
Typedef,
|
||||||
|
Enum,
|
||||||
|
Struct,
|
||||||
|
Union,
|
||||||
|
Note,
|
||||||
|
List,
|
||||||
|
Pointer,
|
||||||
|
Array,
|
||||||
|
Function,
|
||||||
|
Variable,
|
||||||
|
EnumChild,
|
||||||
|
};
|
||||||
|
|
||||||
|
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*;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Parser_Error{
|
||||||
|
next: Parser_Error*;
|
||||||
|
message: String;
|
||||||
|
token: Token*;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Scope{
|
||||||
|
next: Scope*;
|
||||||
|
first: AST_Node*;
|
||||||
|
last: AST_Node*;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
266
parse_decl.c
266
parse_decl.c
@@ -1,20 +1,88 @@
|
|||||||
#if 0
|
function Decl *parse_decl(Parser *p);
|
||||||
|
function Decl *parse_struct(Parser *p, Token *name, Decl_Kind kind);
|
||||||
|
function Typespec *parse_type(Parser *p);
|
||||||
|
|
||||||
function Token *
|
function Typespec *
|
||||||
parse__get_name(Parser *p){
|
parse_type_struct(Parser *p, Token *token){
|
||||||
Token *name = token_next(p);
|
Decl_Kind kind = intern_compare(token->intern_val, keyword_struct) ? DECL_Struct : DECL_Union;
|
||||||
token_next(p);
|
Decl *decl = parse_struct(p, token, kind);
|
||||||
token_next(p);
|
decl->name = (Intern_String){};
|
||||||
return name;
|
return typespec_struct(p, token, decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Typespec *
|
||||||
|
parse_type_function(Parser *p, Token *token){
|
||||||
|
Typespec *result = typespec_function(p, token, 0);
|
||||||
|
if(!token_is(p, TK_CloseParen))
|
||||||
|
for(;;) {
|
||||||
|
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){
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
parser_push_error(p, token, "Failed to parse type, unexpected token");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
function void
|
||||||
parse_note_list(Parser *ctx, AST_Node *parent) {
|
parse_note_list(Parser *ctx, Note *parent) {
|
||||||
if(token_match(ctx, TK_OpenParen)) {
|
if(token_match(ctx, TK_OpenParen)) {
|
||||||
do {
|
do {
|
||||||
Token *name = token_expect(ctx, TK_Identifier);
|
Token *name = token_expect(ctx, TK_Identifier);
|
||||||
AST_Node *current = ast_note(ctx, name, name->intern_val, 0);
|
Note *current = note_push_new(ctx, parent, name, name->intern_val, 0);
|
||||||
ast_node_push_note(parent, current);
|
|
||||||
parse_note_list(ctx, current);
|
parse_note_list(ctx, current);
|
||||||
if(token_match(ctx, TK_Assign)) {
|
if(token_match(ctx, TK_Assign)) {
|
||||||
current->expr = parse_expr(ctx);
|
current->expr = parse_expr(ctx);
|
||||||
@@ -25,11 +93,10 @@ parse_note_list(Parser *ctx, AST_Node *parent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
parse__notes(Parser *ctx, AST_Node *result) {
|
parse__notes(Parser *ctx, Note *result) {
|
||||||
while(token_match(ctx, TK_At)) {
|
while(token_match(ctx, TK_At)) {
|
||||||
Token *name = token_expect(ctx, TK_Identifier);
|
Token *name = token_expect(ctx, TK_Identifier);
|
||||||
AST_Node *current = ast_note(ctx, name, name->intern_val, 0);
|
Note *current = note_push_new(ctx, result, name, name->intern_val, 0);
|
||||||
ast_node_push_note(result, current);
|
|
||||||
parse_note_list(ctx, current);
|
parse_note_list(ctx, current);
|
||||||
if(token_match(ctx, TK_Assign)) {
|
if(token_match(ctx, TK_Assign)) {
|
||||||
current->expr = parse_expr(ctx);
|
current->expr = parse_expr(ctx);
|
||||||
@@ -37,20 +104,151 @@ parse__notes(Parser *ctx, AST_Node *result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function AST_Node
|
function Note
|
||||||
parse_notes(Parser *p){
|
parse_notes(Parser *p){
|
||||||
AST_Node result = {};
|
Note result = {};
|
||||||
parse__notes(p, &result);
|
parse__notes(p, &result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AST_Node *
|
function Decl *
|
||||||
parse_enum(Parser *p, Token *name){
|
parse_enum(Parser *p, Token *name){
|
||||||
AST_Node *result = 0;
|
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, ¬es);
|
||||||
|
} 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 *result = decl_struct(p, kind, name, name->intern_val);
|
||||||
|
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 {
|
||||||
|
parser_push_error(p, token_get(p), "Unexpected token while parsing struct");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
token_expect(p, TK_Semicolon);
|
||||||
|
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 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_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);
|
||||||
|
}
|
||||||
|
else if(token_peek_is_keyword(p, 2, keyword_union)){
|
||||||
|
result = parse_struct(p, parse_get_token_name(p,2), DECL_Union);
|
||||||
|
}
|
||||||
|
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, 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result){
|
||||||
|
result->first_note = notes.first;
|
||||||
|
result->last_note = notes.last;
|
||||||
|
}
|
||||||
|
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){});
|
||||||
|
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 Token *
|
||||||
|
parse__get_name(Parser *p){
|
||||||
|
Token *name = token_next(p);
|
||||||
|
token_next(p);
|
||||||
|
token_next(p);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Note *
|
||||||
|
parse_enum(Parser *p, Token *name){
|
||||||
|
Note *result = 0;
|
||||||
if(token_expect(p, TK_OpenBrace)){
|
if(token_expect(p, TK_OpenBrace)){
|
||||||
result = ast_enum(p, name, name->intern_val);
|
result = ast_enum(p, name, name->intern_val);
|
||||||
do{
|
do{
|
||||||
AST_Node notes = parse_notes(p);
|
Note notes = parse_notes(p);
|
||||||
Token *token = token_match(p, TK_Identifier);
|
Token *token = token_match(p, TK_Identifier);
|
||||||
if(token){
|
if(token){
|
||||||
Expr *expr = 0;
|
Expr *expr = 0;
|
||||||
@@ -58,7 +256,7 @@ parse_enum(Parser *p, Token *name){
|
|||||||
expr = parse_expr(p);
|
expr = parse_expr(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_Node *child = ast_enum_child(p, token, token->intern_val, expr);
|
Note *child = ast_enum_child(p, token, token->intern_val, expr);
|
||||||
ast_node_pass_note_list(child,¬es);
|
ast_node_pass_note_list(child,¬es);
|
||||||
ast_node_push_child(result, child);
|
ast_node_push_child(result, child);
|
||||||
}
|
}
|
||||||
@@ -71,12 +269,12 @@ parse_enum(Parser *p, Token *name){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AST_Node *
|
function Note *
|
||||||
parse_variable(Parser *p, Token *name){
|
parse_variable(Parser *p, Token *name){
|
||||||
AST_Node *result = 0;
|
Note *result = 0;
|
||||||
Token *type_token = token_expect(p, TK_Identifier);
|
Token *type_token = token_expect(p, TK_Identifier);
|
||||||
if(type_token){
|
if(type_token){
|
||||||
AST_Node *type = symbol_require_type(p, type_token);
|
Note *type = symbol_require_type(p, type_token);
|
||||||
Token *star;
|
Token *star;
|
||||||
while((star = token_match(p, TK_Mul))){
|
while((star = token_match(p, TK_Mul))){
|
||||||
type = ast_type_pointer(p, star, type);
|
type = ast_type_pointer(p, star, type);
|
||||||
@@ -95,16 +293,16 @@ parse_variable(Parser *p, Token *name){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AST_Node *
|
function Note *
|
||||||
parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){
|
parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){
|
||||||
AST_Node *result = 0;
|
Note *result = 0;
|
||||||
if(token_expect(p, TK_OpenBrace)){
|
if(token_expect(p, TK_OpenBrace)){
|
||||||
result = ast_struct(p, name, name?name->intern_val:(Intern_String){}, kind);
|
result = ast_struct(p, name, name?name->intern_val:(Intern_String){}, kind);
|
||||||
if(is_global) symbol_register(p, result);
|
if(is_global) symbol_register(p, result);
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
AST_Node notes = parse_notes(p);
|
Note notes = parse_notes(p);
|
||||||
AST_Node *mem = 0;
|
Note *mem = 0;
|
||||||
Token *mem_name = token_match(p, TK_Identifier);
|
Token *mem_name = token_match(p, TK_Identifier);
|
||||||
if(mem_name){
|
if(mem_name){
|
||||||
if(token_expect(p, TK_Colon)){
|
if(token_expect(p, TK_Colon)){
|
||||||
@@ -157,22 +355,22 @@ parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AST_Node *
|
function Note *
|
||||||
parse_typedef(Parser *p, Token *name){
|
parse_typedef(Parser *p, Token *name){
|
||||||
Token *type_token = token_expect(p, TK_Identifier);
|
Token *type_token = token_expect(p, TK_Identifier);
|
||||||
AST_Node *type = symbol_require_type(p, type_token);
|
Note *type = symbol_require_type(p, type_token);
|
||||||
AST_Node *result = ast_typedef(p, name, name->intern_val, type);
|
Note *result = ast_typedef(p, name, name->intern_val, type);
|
||||||
token_expect(p, TK_Semicolon);
|
token_expect(p, TK_Semicolon);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AST_Node_List *
|
function Note_List *
|
||||||
parse(Parser *p){
|
parse(Parser *p){
|
||||||
AST_Node_List *result = ast_node_new(p, AK_List, token_get(p), intern_empty);
|
Note_List *result = ast_node_new(p, AK_List, token_get(p), intern_empty);
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
AST_Node *node = 0;
|
Note *node = 0;
|
||||||
AST_Node notes = parse_notes(p);
|
Note notes = parse_notes(p);
|
||||||
|
|
||||||
if(token_is(p, TK_End)){
|
if(token_is(p, TK_End)){
|
||||||
break;
|
break;
|
||||||
@@ -218,4 +416,4 @@ parse(Parser *p){
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
*/
|
||||||
49
parse_expr.c
49
parse_expr.c
@@ -1,5 +1,6 @@
|
|||||||
function Expr* parse_expr(Parser* p);
|
function Expr* parse_expr(Parser* p);
|
||||||
function Expr* parse_list_expr(Parser* p);
|
function Expr* parse_list_expr(Parser* p);
|
||||||
|
function Typespec *parse_type(Parser *p);
|
||||||
|
|
||||||
function Expr*
|
function Expr*
|
||||||
parse_atom_expr(Parser* p){
|
parse_atom_expr(Parser* p){
|
||||||
@@ -10,6 +11,21 @@ parse_atom_expr(Parser* p){
|
|||||||
token_is(p, TK_Int)){
|
token_is(p, TK_Int)){
|
||||||
result = expr_atom(p, token_next(p));
|
result = expr_atom(p, token_next(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (token_is_keyword(p, keyword_sizeof)) {
|
||||||
|
Token *token = token_next(p);
|
||||||
|
token_expect(p, TK_OpenParen);
|
||||||
|
Typespec *type = 0;
|
||||||
|
Expr *expr = 0;
|
||||||
|
if(token_match(p, TK_Colon)) {
|
||||||
|
result = expr_sizeof_type(p, token, parse_type(p));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = expr_sizeof_expr(p, token, parse_expr(p));
|
||||||
|
}
|
||||||
|
token_expect(p, TK_CloseParen);
|
||||||
|
}
|
||||||
|
|
||||||
else if (token_match(p, TK_OpenParen)){
|
else if (token_match(p, TK_OpenParen)){
|
||||||
result = parse_list_expr(p);
|
result = parse_list_expr(p);
|
||||||
token_expect(p, TK_CloseParen);
|
token_expect(p, TK_CloseParen);
|
||||||
@@ -24,17 +40,13 @@ function Expr*
|
|||||||
parse_postfix_expr(Parser* p){
|
parse_postfix_expr(Parser* p){
|
||||||
Expr* result = parse_atom_expr(p);
|
Expr* result = parse_atom_expr(p);
|
||||||
while (token_is(p, TK_Dot)
|
while (token_is(p, TK_Dot)
|
||||||
|| token_is(p, TK_Arrow)
|
|
||||||
|| token_is(p, TK_DoubleColon)
|
|
||||||
|| token_is(p, TK_OpenParen)
|
|| token_is(p, TK_OpenParen)
|
||||||
|| token_is(p, TK_OpenBracket)
|
|| token_is(p, TK_OpenBracket)
|
||||||
|| token_is(p, TK_Decrement)
|
|| token_is(p, TK_Decrement)
|
||||||
|| token_is(p, TK_Increment)){
|
|| token_is(p, TK_Increment)){
|
||||||
Token *op = token_get(p);
|
Token *op = token_get(p);
|
||||||
|
|
||||||
if (token_match(p, TK_Arrow)
|
if (token_match(p, TK_Dot)){
|
||||||
|| token_match(p, TK_DoubleColon)
|
|
||||||
|| token_match(p, TK_Dot)){
|
|
||||||
Expr* r = parse_atom_expr(p);
|
Expr* r = parse_atom_expr(p);
|
||||||
result = expr_binary(p, op, result, r);
|
result = expr_binary(p, op, result, r);
|
||||||
}
|
}
|
||||||
@@ -85,35 +97,16 @@ Expr* parse_unary_expr(Parser* p) {
|
|||||||
result = parse_unary_expr(p);
|
result = parse_unary_expr(p);
|
||||||
result = expr_unary(p, op, result);
|
result = expr_unary(p, op, result);
|
||||||
}
|
}
|
||||||
else if (token_is_keyword(p, keyword_sizeof)) {
|
|
||||||
Token *token = token_next(p);
|
|
||||||
result = parse_unary_expr(p);
|
|
||||||
result = expr_unary(p, token, result);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
else if (token_is(p, TK_OpenParen)) { // cast requires lookahead
|
|
||||||
Token *token = token_peek(p, 1);
|
|
||||||
if (token->kind == TK_Identifier) {
|
|
||||||
|
|
||||||
AST_Node *type = symbol_lookup_type(p, token->intern_val);
|
else if (token_is_keyword(p, keyword_cast)) {
|
||||||
if(type){
|
Token *token = token_next(p);
|
||||||
token_next(p);
|
token_expect(p, TK_OpenParen);
|
||||||
token_next(p);
|
Typespec *type = parse_type(p);
|
||||||
// @Todo(Krzosa): Parse pointer types
|
|
||||||
token_expect(p, TK_CloseParen);
|
token_expect(p, TK_CloseParen);
|
||||||
result = parse_unary_expr(p);
|
result = parse_unary_expr(p);
|
||||||
result = expr_cast(p, token, type, result);
|
result = expr_cast(p, token, type, result);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
result = parse_postfix_expr(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = parse_postfix_expr(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
else {
|
else {
|
||||||
result = parse_postfix_expr(p);
|
result = parse_postfix_expr(p);
|
||||||
}
|
}
|
||||||
|
|||||||
7
parser.c
7
parser.c
@@ -14,6 +14,7 @@ global Intern_String intern_void;
|
|||||||
global Intern_String intern_sizeu;
|
global Intern_String intern_sizeu;
|
||||||
|
|
||||||
global Intern_String keyword_sizeof;
|
global Intern_String keyword_sizeof;
|
||||||
|
global Intern_String keyword_cast;
|
||||||
global Intern_String keyword_enum;
|
global Intern_String keyword_enum;
|
||||||
global Intern_String keyword_typedef;
|
global Intern_String keyword_typedef;
|
||||||
global Intern_String keyword_struct;
|
global Intern_String keyword_struct;
|
||||||
@@ -27,6 +28,7 @@ parser_init(Parser *p){
|
|||||||
p->interns = arena_push_array(&p->intern_table_arena, Intern_String, p->interns_count);
|
p->interns = arena_push_array(&p->intern_table_arena, Intern_String, p->interns_count);
|
||||||
|
|
||||||
keyword_sizeof = intern_string(p, lit("sizeof"));
|
keyword_sizeof = intern_string(p, lit("sizeof"));
|
||||||
|
keyword_cast = intern_string(p, lit("cast"));
|
||||||
keyword_struct = intern_string(p, lit("struct"));
|
keyword_struct = intern_string(p, lit("struct"));
|
||||||
keyword_enum = intern_string(p, lit("enum"));
|
keyword_enum = intern_string(p, lit("enum"));
|
||||||
keyword_typedef = intern_string(p, lit("typedef"));
|
keyword_typedef = intern_string(p, lit("typedef"));
|
||||||
@@ -36,7 +38,6 @@ parser_init(Parser *p){
|
|||||||
p->first_keyword = keyword_sizeof.s.str;
|
p->first_keyword = keyword_sizeof.s.str;
|
||||||
p->last_keyword = keyword_global.s.str;
|
p->last_keyword = keyword_global.s.str;
|
||||||
|
|
||||||
|
|
||||||
intern_s64 = intern_string(p, lit("S64"));
|
intern_s64 = intern_string(p, lit("S64"));
|
||||||
intern_s32 = intern_string(p, lit("S32"));
|
intern_s32 = intern_string(p, lit("S32"));
|
||||||
intern_s16 = intern_string(p, lit("S16"));
|
intern_s16 = intern_string(p, lit("S16"));
|
||||||
@@ -60,7 +61,6 @@ intern_is_keyword(Parser *p, Intern_String intern){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
parser_push_error(Parser *p, Token *token, char *str, ...){
|
parser_push_error(Parser *p, Token *token, char *str, ...){
|
||||||
|
|
||||||
String string;
|
String string;
|
||||||
{
|
{
|
||||||
va_list args1, args2;
|
va_list args1, args2;
|
||||||
@@ -80,6 +80,9 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
|
|||||||
error->next = 0;
|
error->next = 0;
|
||||||
error->token = token;
|
error->token = token;
|
||||||
SLLQueuePush(p->first_error, p->last_error, error);
|
SLLQueuePush(p->first_error, p->last_error, error);
|
||||||
|
|
||||||
|
__debugbreak();
|
||||||
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
|
|||||||
219
print.c
Normal file
219
print.c
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
function void print_decl(Parser *p, Decl *node);
|
||||||
|
function B32 print_typespec(Parser *p, Typespec *spec);
|
||||||
|
|
||||||
|
function void
|
||||||
|
tokens_print(Tokens tokens){
|
||||||
|
lex_print("\n== Token count = %d\n", (S32)tokens.len);
|
||||||
|
for(Token *t = tokens.tokens; t != tokens.tokens + tokens.len; t++){
|
||||||
|
lex_print("%s \"%.*s\"\n", token_kind_string[t->kind].str, (S32)t->len, t->str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
token_print(Token *token){
|
||||||
|
lex_print("%.*s", (S32)token->len, token->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
expr_print(Parser *p, Expr *expr){
|
||||||
|
switch(expr->kind) {
|
||||||
|
case EK_Atom: {
|
||||||
|
token_print(expr->token);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_Sizeof:{
|
||||||
|
lex_print("sizeof(");
|
||||||
|
if(expr->size_of.kind == SIZEOF_Expr){
|
||||||
|
expr_print(p, expr->size_of.expr);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
assert(expr->size_of.kind == SIZEOF_Type);
|
||||||
|
print_typespec(p, expr->size_of.type);
|
||||||
|
}
|
||||||
|
lex_print(")");
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case EK_Binary:{
|
||||||
|
lex_print("(");
|
||||||
|
expr_print(p, expr->binary.left);
|
||||||
|
token_print(expr->token);
|
||||||
|
expr_print(p, expr->binary.right);
|
||||||
|
lex_print(")");
|
||||||
|
} break;
|
||||||
|
case EK_Unary:{
|
||||||
|
lex_print("(");
|
||||||
|
token_print(expr->token);
|
||||||
|
expr_print(p, expr->unary.expr);
|
||||||
|
lex_print(")");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_Ternary:{
|
||||||
|
lex_print("(");
|
||||||
|
expr_print(p, expr->ternary.cond);
|
||||||
|
lex_print("?");
|
||||||
|
expr_print(p, expr->ternary.on_true);
|
||||||
|
lex_print(":");
|
||||||
|
expr_print(p, expr->ternary.on_false);
|
||||||
|
lex_print(")");
|
||||||
|
} break;
|
||||||
|
case EK_List:{
|
||||||
|
lex_print("(");
|
||||||
|
for(Expr *n = expr->list.first; n; n=n->next){
|
||||||
|
expr_print(p, n);
|
||||||
|
if(n!=expr->list.last) lex_print(",");
|
||||||
|
}
|
||||||
|
lex_print(")");
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case EK_Cast:{
|
||||||
|
lex_print("(");
|
||||||
|
lex_print("(");
|
||||||
|
print_typespec(p, expr->cast.type);
|
||||||
|
lex_print(")");
|
||||||
|
expr_print(p, expr->cast.expr);
|
||||||
|
lex_print(")");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_Index:{
|
||||||
|
expr_print(p, expr->index.atom);
|
||||||
|
lex_print("[");
|
||||||
|
expr_print(p, expr->index.index);
|
||||||
|
lex_print("]");
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case EK_Call:{
|
||||||
|
expr_print(p, expr->call.atom);
|
||||||
|
lex_print("(");
|
||||||
|
expr_print(p, expr->call.list);
|
||||||
|
lex_print(")");
|
||||||
|
}break;
|
||||||
|
default: {invalid_codepath;} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global S64 indent;
|
||||||
|
|
||||||
|
|
||||||
|
function B32
|
||||||
|
print_typespec(Parser *p, Typespec *spec){
|
||||||
|
switch(spec->kind) {
|
||||||
|
case TS_Name: {
|
||||||
|
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);
|
||||||
|
lex_print("*");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TS_Array: {
|
||||||
|
print_typespec(p, spec->array_spec.base);
|
||||||
|
lex_print("[");
|
||||||
|
expr_print(p, spec->array_spec.size);
|
||||||
|
lex_print("]");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TS_Function: {
|
||||||
|
lex_print("(");
|
||||||
|
for(Typespec *n = spec->function_spec.first; n; n=n->next){
|
||||||
|
print_typespec(p,n);
|
||||||
|
if(n!=spec->function_spec.last)
|
||||||
|
lex_print(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
lex_print(")");
|
||||||
|
print_typespec(p,spec->function_spec.ret);
|
||||||
|
} break;
|
||||||
|
default: {invalid_codepath;} break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
print_assign_expr(Parser *p, Expr *expr){
|
||||||
|
if(expr){
|
||||||
|
lex_print(" = ");
|
||||||
|
expr_print(p, expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
print_note_list(Parser *p, Note *note){
|
||||||
|
if(note){
|
||||||
|
lex_print("(");
|
||||||
|
for(Note *n = note; n; n=n->next){
|
||||||
|
lex_print("%s", n->name.s.str);
|
||||||
|
print_note_list(p,n->first);
|
||||||
|
print_assign_expr(p, n->expr);
|
||||||
|
}
|
||||||
|
lex_print(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
print_notes(Parser *p, Note *note){
|
||||||
|
for(Note *n = note; n; n=n->next){
|
||||||
|
lex_print("@%s", n->name.s.str);
|
||||||
|
print_note_list(p,n->first);
|
||||||
|
print_assign_expr(p,n->expr);
|
||||||
|
lex_print(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
print_decl(Parser *p, Decl *node){
|
||||||
|
print_notes(p, node->first_note);
|
||||||
|
|
||||||
|
switch(node->kind) {
|
||||||
|
case DECL_List: {
|
||||||
|
for(Decl *n = node->list.first; n; n=n->next){
|
||||||
|
print_decl(p,n);
|
||||||
|
lex_new_line();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DECL_Variable:{
|
||||||
|
lex_print("%s: ", node->name.s.str);
|
||||||
|
B32 r = print_typespec(p, node->variable_decl.type);
|
||||||
|
print_assign_expr(p,node->variable_decl.expr);
|
||||||
|
if(r) lex_print(";");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DECL_Typedef:{
|
||||||
|
lex_print("typedef %s ", node->name.s.str);
|
||||||
|
print_typespec(p, node->typedef_decl.type);
|
||||||
|
lex_print(";");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DECL_Struct:
|
||||||
|
case DECL_Union :{
|
||||||
|
const char *struct_name = node->kind==DECL_Struct ? "struct" : "union";
|
||||||
|
lex_print("%s %s{\n", struct_name, node->name.s.str?(char*)node->name.s.str:"");
|
||||||
|
for(Decl *n = node->struct_decl.first; n; n=n->next){
|
||||||
|
print_decl(p, n);
|
||||||
|
lex_print("\n");
|
||||||
|
}
|
||||||
|
lex_print("};\n");
|
||||||
|
} break;
|
||||||
|
case DECL_Enum:{
|
||||||
|
lex_print("enum %s : ", node->name.s.str);
|
||||||
|
print_typespec(p, node->enum_decl.typespec);
|
||||||
|
lex_print("{\n");
|
||||||
|
for(Decl_Enum_Child *n = node->enum_decl.first; n; n=n->next){
|
||||||
|
print_notes(p, n->first_note);
|
||||||
|
lex_print("%s", n->name.s.str);
|
||||||
|
print_assign_expr(p, n->expr);
|
||||||
|
lex_print(",\n");
|
||||||
|
}
|
||||||
|
lex_print("};\n");
|
||||||
|
} break;
|
||||||
|
default: {invalid_codepath;} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
66
test.cc
66
test.cc
@@ -1,26 +1,26 @@
|
|||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
OS_Memory:struct{
|
OS_Memory::struct{
|
||||||
data: void*;
|
data: void*;
|
||||||
commit: SizeU;
|
commit: SizeU;
|
||||||
reserve: SizeU;
|
reserve: SizeU;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arena:struct{
|
Arena::struct{
|
||||||
@using memory: OS_Memory;
|
@using memory: OS_Memory;
|
||||||
len: U64;
|
len: U64;
|
||||||
alignment: U64;
|
alignment: U64;
|
||||||
}
|
}
|
||||||
|
|
||||||
String:struct{
|
String::struct{
|
||||||
str: U8*;
|
str: U8*;
|
||||||
len: S64;
|
len: S64;
|
||||||
}
|
}
|
||||||
Intern_String:typedef String;
|
Intern_String::typedef String;
|
||||||
|
|
||||||
@stringify
|
@stringify
|
||||||
@prefix="TK_"
|
@prefix="TK_"
|
||||||
Token_Kind:enum{
|
Token_Kind::enum{
|
||||||
@str="End of stream" End,
|
@str="End of stream" End,
|
||||||
@str="*" Mul,
|
@str="*" Mul,
|
||||||
@str="/" Div,
|
@str="/" Div,
|
||||||
@@ -86,25 +86,25 @@ Token_Kind:enum{
|
|||||||
Keyword,
|
Keyword,
|
||||||
}
|
}
|
||||||
|
|
||||||
Token:struct{
|
Token::struct{
|
||||||
kind:Token_Kind;
|
kind:Token_Kind;
|
||||||
@using string:String;
|
@using string:String;
|
||||||
union:{
|
val: union{
|
||||||
int_val:S64;
|
integer:S64;
|
||||||
error_val:String;
|
error:String;
|
||||||
intern_val:Intern_String;
|
intern:Intern_String;
|
||||||
}
|
};
|
||||||
file:String;
|
file:String;
|
||||||
line:S64;
|
line:S64;
|
||||||
line_begin:U8*;
|
line_begin:U8*;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokens:struct{
|
Tokens::struct{
|
||||||
@array tokens: Token*;
|
@array tokens: Token*;
|
||||||
iter : S64;
|
iter : S64;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lex_Stream:struct{
|
Lex_Stream::struct{
|
||||||
stream: U8*;
|
stream: U8*;
|
||||||
line_begin: U8*;
|
line_begin: U8*;
|
||||||
filename: String;
|
filename: String;
|
||||||
@@ -112,7 +112,7 @@ Lex_Stream:struct{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@prefix="EK_"
|
@prefix="EK_"
|
||||||
Expr_Kind: enum{
|
Expr_Kind::enum{
|
||||||
None,
|
None,
|
||||||
Atom,
|
Atom,
|
||||||
Unary,
|
Unary,
|
||||||
@@ -124,46 +124,44 @@ Expr_Kind: enum{
|
|||||||
Index,
|
Index,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
Expr:: struct{
|
||||||
Expr: struct{
|
|
||||||
kind: Expr_Kind;
|
kind: Expr_Kind;
|
||||||
token: Token*;
|
token: Token*;
|
||||||
next : Expr*;
|
next : Expr*;
|
||||||
union:{
|
_: union{
|
||||||
cast: struct{
|
cast_val: struct{
|
||||||
type: AST_Node*;
|
type: AST_Node*;
|
||||||
expr: Expr*;
|
expr: Expr*;
|
||||||
}
|
};
|
||||||
list: struct{
|
list: struct{
|
||||||
first: Expr *;
|
first: Expr *;
|
||||||
last: Expr *;
|
last: Expr *;
|
||||||
}
|
};
|
||||||
call: struct{
|
call: struct{
|
||||||
atom: Expr *;
|
atom: Expr *;
|
||||||
list: Expr *;
|
list: Expr *;
|
||||||
}
|
};
|
||||||
index: struct{
|
index: struct{
|
||||||
atom: Expr *;
|
atom: Expr *;
|
||||||
index: Expr *;
|
index: Expr *;
|
||||||
}
|
};
|
||||||
unary: struct{
|
unary: struct{
|
||||||
expr: Expr* ;
|
expr: Expr* ;
|
||||||
}
|
};
|
||||||
binary: struct{
|
binary: struct{
|
||||||
left: Expr* ;
|
left: Expr* ;
|
||||||
right: Expr* ;
|
right: Expr* ;
|
||||||
}
|
};
|
||||||
ternary: struct{
|
ternary: struct{
|
||||||
cond: Expr* ;
|
cond: Expr* ;
|
||||||
on_true: Expr*;
|
on_true: Expr*;
|
||||||
on_false: Expr*;
|
on_false: Expr*;
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
@prefix="AK_"
|
@prefix="AK_"
|
||||||
AST_Kind:enum{
|
AST_Kind::enum{
|
||||||
None,
|
None,
|
||||||
BaseType,
|
BaseType,
|
||||||
Typedef,
|
Typedef,
|
||||||
@@ -179,7 +177,7 @@ AST_Kind:enum{
|
|||||||
EnumChild,
|
EnumChild,
|
||||||
}
|
}
|
||||||
|
|
||||||
AST_Node:struct{
|
AST_Node::struct{
|
||||||
kind: AST_Kind;
|
kind: AST_Kind;
|
||||||
pos : Token*;
|
pos : Token*;
|
||||||
name: Intern_String;
|
name: Intern_String;
|
||||||
@@ -192,28 +190,28 @@ AST_Node:struct{
|
|||||||
|
|
||||||
first_child: AST_Node*;
|
first_child: AST_Node*;
|
||||||
last_child: AST_Node*;
|
last_child: AST_Node*;
|
||||||
union:{
|
_:union{
|
||||||
base_type_size: SizeU;
|
base_type_size: SizeU;
|
||||||
pointer: AST_Node*;
|
pointer: AST_Node*;
|
||||||
typedef_type: AST_Node*;
|
typedef_type: AST_Node*;
|
||||||
variable_type: AST_Node*;
|
variable_type: AST_Node*;
|
||||||
func_return_type: AST_Node*;
|
func_return_type: AST_Node*;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser_Error: struct{
|
Parser_Error :: struct{
|
||||||
next: Parser_Error*;
|
next: Parser_Error*;
|
||||||
message: String;
|
message: String;
|
||||||
token : Token *;
|
token : Token *;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope: struct{
|
Scope :: struct{
|
||||||
next : Scope*;
|
next : Scope*;
|
||||||
first: AST_Node*;
|
first: AST_Node*;
|
||||||
last : AST_Node*;
|
last : AST_Node*;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser: struct{
|
Parser :: struct{
|
||||||
main_arena: Arena;
|
main_arena: Arena;
|
||||||
intern_table_arena: Arena;
|
intern_table_arena: Arena;
|
||||||
symbol_table_arena: Arena;
|
symbol_table_arena: Arena;
|
||||||
|
|||||||
Reference in New Issue
Block a user