Generating valid c code, more work on null values
This commit is contained in:
74
parse.c
74
parse.c
@@ -9,7 +9,7 @@ struct Parser_Error{
|
||||
typedef struct Parser{
|
||||
Token_Array tokens;
|
||||
Arena *arena;
|
||||
|
||||
|
||||
Parser_Error *first_error;
|
||||
Parser_Error *last_error;
|
||||
}Parser;
|
||||
@@ -38,36 +38,36 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
|
||||
va_copy(args2, args1);
|
||||
string.len = vsnprintf(0, 0, str, args2);
|
||||
va_end(args2);
|
||||
|
||||
|
||||
string.str = arena_push_size(p->arena, string.len + 1);
|
||||
vsnprintf((char*)string.str, string.len + 1, str, args1);
|
||||
va_end(args1);
|
||||
}
|
||||
|
||||
|
||||
// @Note(Krzosa): Print nice error message
|
||||
printf("\nError: %s", string.str);
|
||||
if(token){
|
||||
printf(" %s:%d\n", token->file.str, (S32)token->line);
|
||||
|
||||
|
||||
// @Note(Krzosa): Print error line
|
||||
{
|
||||
int i = 0;
|
||||
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
||||
printf("%.*s\n", i, token->line_begin);
|
||||
|
||||
|
||||
// @Note(Krzosa): Print error marker
|
||||
int token_i = token->str - token->line_begin;
|
||||
for(int i = 0; i < token_i-2; i++) printf(" ");
|
||||
printf("^^^^^^\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Parser_Error *error = arena_push_struct(p->arena, Parser_Error);
|
||||
error->message = string;
|
||||
error->next = 0;
|
||||
error->token = token;
|
||||
SLLQueuePush(p->first_error, p->last_error, error);
|
||||
|
||||
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
@@ -162,15 +162,15 @@ compare = == | != | >= | > | <= | <
|
||||
logical = [&|^] | && | ||
|
||||
unary = [&*-!~+] | ++ | --
|
||||
|
||||
atom_expr = Int
|
||||
| Float
|
||||
| String
|
||||
atom_expr = Int
|
||||
| Float
|
||||
| String
|
||||
| Identifier
|
||||
| 'cast' '(' typespec ',' expr ')'
|
||||
| 'size_type' '(' typespec ')'
|
||||
| 'size_expr' '(' expr ')'
|
||||
| '{' compound_expr '}'
|
||||
| '(' expr ')'
|
||||
| '(' expr ')'
|
||||
| '(' ':' typespec ')' '{' compound_expr '}'
|
||||
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
|
||||
unary_expr = unary ? unary_expr : atom_expr
|
||||
@@ -205,7 +205,7 @@ parse_expr_compound_field(Parser *p){
|
||||
parser_push_error(p, token, "Failed to parse compound literal, required identifier as left value");
|
||||
}
|
||||
result = expr_compound_named(p->arena, token, expr->intern_val, parse_expr(p));
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
result = expr_compound_default(p->arena, token, expr);
|
||||
@@ -251,7 +251,7 @@ parse_expr_atom(Parser *p){
|
||||
else if(token_is(p, TK_OpenBrace)){
|
||||
result = parse_expr_compound(p, 0);
|
||||
}
|
||||
|
||||
|
||||
else if(token_match(p, TK_OpenParen)){
|
||||
if(token_match(p, TK_Colon)){
|
||||
Typespec *typespec = parse_typespec(p);
|
||||
@@ -343,7 +343,7 @@ parse_expr_postfix(Parser *p){
|
||||
function B32
|
||||
token_is_unary(Parser *p){
|
||||
Token *token = token_get(p);
|
||||
B32 result = token->kind == TK_Add
|
||||
B32 result = token->kind == TK_Add
|
||||
|| token->kind == TK_Increment
|
||||
|| token->kind == TK_Decrement
|
||||
|| token->kind == TK_Sub
|
||||
@@ -462,15 +462,15 @@ parse_expr(Parser *p){
|
||||
// Type specifier parsing
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
base_type = NAME
|
||||
base_type = NAME
|
||||
| '(' type_list? ')' type?
|
||||
|
||||
type = ('*' | '[' expr ']')* base_type
|
||||
|
||||
Examples:
|
||||
Examples:
|
||||
[32]*U32 - Array of 32 pointers to U32
|
||||
**CustomDataType - Pointer to pointer of CustomDataType
|
||||
(*U32, S64) **S64 - Function pointer
|
||||
(*U32, S64) **S64 - Function pointer
|
||||
(CoolType: optional, S32) - Implicit void return value
|
||||
|
||||
*/
|
||||
@@ -490,9 +490,9 @@ parse_optional_type(Parser *p, Intern_String type){
|
||||
function Typespec *
|
||||
parse_typespec_function(Parser *p, Token *token){
|
||||
Typespec *result = typespec_function(p->arena, token, 0);
|
||||
if(!token_is(p, TK_CloseParen))
|
||||
if(!token_is(p, TK_CloseParen))
|
||||
for(;;) {
|
||||
|
||||
|
||||
// Optional name
|
||||
Token *name = 0;
|
||||
if((token = token_is(p, TK_Identifier))){
|
||||
@@ -502,21 +502,21 @@ parse_typespec_function(Parser *p, Token *token){
|
||||
name = token;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parse type
|
||||
Typespec *arg = parse_typespec(p);
|
||||
if(name)
|
||||
if(name)
|
||||
arg = typespec_named_argument(p->arena, name, arg, name->intern_val);
|
||||
typespec_function_push(result, arg);
|
||||
|
||||
|
||||
if(!token_match(p, TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
token_expect(p, TK_CloseParen);
|
||||
|
||||
|
||||
result->func.ret = parse_optional_type(p, intern_void);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -578,7 +578,7 @@ name::const = 4254;
|
||||
// }
|
||||
// }
|
||||
*/
|
||||
function void
|
||||
function void
|
||||
parse_note_list(Parser *p, AST_Parent *parent) {
|
||||
if(token_match(p, TK_OpenParen)) {
|
||||
if(token_match(p, TK_CloseParen)){
|
||||
@@ -596,7 +596,7 @@ parse_note_list(Parser *p, AST_Parent *parent) {
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
function void
|
||||
parse__notes(Parser *p, AST_Parent *result) {
|
||||
while(token_match(p, TK_At)) {
|
||||
Token *name = token_expect(p, TK_Identifier);
|
||||
@@ -791,7 +791,7 @@ parse_decl(Parser *p, AST_Parent *parent){
|
||||
"token '%s'", token_kind_string[token->kind]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(result){
|
||||
result->notes = note;
|
||||
ast_push_last(parent, result);
|
||||
@@ -806,7 +806,7 @@ parse_decl(Parser *p, AST_Parent *parent){
|
||||
function AST *parse_stmt(Parser *p);
|
||||
/*
|
||||
stmt_list = '{' stmt* '}'
|
||||
stmt =
|
||||
stmt =
|
||||
| stmt_list
|
||||
| 'return' expr ';'
|
||||
| 'if' expr stmt_list
|
||||
@@ -969,11 +969,11 @@ parse_stmt(Parser *p){
|
||||
result = parse_simple_stmt(p);
|
||||
token_expect(p, TK_Semicolon);
|
||||
}
|
||||
|
||||
|
||||
if(result){
|
||||
result->notes = notes;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1017,7 +1017,7 @@ eval_expr(Expr *expr){
|
||||
case TK_LesserThen: return left < right; break;
|
||||
case TK_BitAnd: return left & right; break;
|
||||
case TK_BitOr: return left | right; break;
|
||||
case TK_BitXor: return left ^ right; break;
|
||||
case TK_Pointer: return left ^ right; break;
|
||||
case TK_And: return left && right; break;
|
||||
case TK_Or: return left || right; break;
|
||||
case TK_LeftShift: return left << right; break;
|
||||
@@ -1083,11 +1083,11 @@ parse_test_expr(){
|
||||
" 1>5 ? 1 : 2 "
|
||||
" !!!!!1 "
|
||||
" ~~1 + -!2 "
|
||||
" 1 + ++Thing[12]++ + ++Thing[12].expr +"
|
||||
" 1 + ++Thing[12]++ + ++Thing[12].expr +"
|
||||
);
|
||||
Parser parser = parser_make_stream(scratch, test_case, lit("Big_Expr"));
|
||||
Parser *p = &parser;
|
||||
|
||||
|
||||
S64 t = 5;
|
||||
S64 test_val[] = {
|
||||
(32+52-242*2/424%5-23),
|
||||
@@ -1106,7 +1106,7 @@ parse_test_expr(){
|
||||
S64 val = eval_expr(expr);
|
||||
assert(val == test_val[i]);
|
||||
}
|
||||
|
||||
|
||||
String exprs[] = {
|
||||
lit("cast([12](thing: U32, qwe: *U32): [32]Result, (123+234))"),
|
||||
lit("cast((thing: U32, qwe: *U32), (123+234))"),
|
||||
@@ -1123,7 +1123,7 @@ parse_test_expr(){
|
||||
expr_print(expr);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
@@ -1131,7 +1131,7 @@ function void
|
||||
parse_test_decls(){
|
||||
Arena *scratch = arena_begin_scratch();
|
||||
Parser p = parser_make(scratch);
|
||||
|
||||
|
||||
String decls[] = {
|
||||
lit("Thing::enum: U64{ Thing_1 = 1<<1, Thing_2 = 2 }"),
|
||||
lit("Struct::struct{ thing, thing2: *S64; struct { thing:U32; thing2: [64]Vec2; } inner: struct {i:U32;} }"),
|
||||
@@ -1156,7 +1156,7 @@ parse_test_from_file(){
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
function void
|
||||
function void
|
||||
parse_test_stmt(){
|
||||
Arena *scratch = arena_begin_scratch();
|
||||
Parser p = parser_make(scratch);
|
||||
|
||||
Reference in New Issue
Block a user