Generating valid c code, more work on null values
This commit is contained in:
@@ -9,12 +9,12 @@ token_get(S64 i = 0){
|
||||
if(result->kind == TK_NewLine){
|
||||
pctx->indent = result->indent;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function Token *
|
||||
token_next(){
|
||||
token_next(){
|
||||
Token *token = token_get();
|
||||
pctx->token_iter++;
|
||||
return token;
|
||||
@@ -51,28 +51,28 @@ token_match_keyword(Intern_String string){
|
||||
}
|
||||
|
||||
function void
|
||||
parsing_error(Token *token, const char *str, ...){
|
||||
parsing_error(Token *token, const char *str, ...){
|
||||
Scratch scratch;
|
||||
STRING_FMT(scratch, str, string);
|
||||
|
||||
|
||||
// @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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
@@ -97,15 +97,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
|
||||
@@ -143,17 +143,17 @@ parse_expr_compound(){
|
||||
name = ast_expr_identifier(token, token->intern_val);
|
||||
token_expect(TK_Assign);
|
||||
}
|
||||
|
||||
|
||||
Ast_Expr *item = parse_expr();
|
||||
Ast_Expr *item_comp = ast_expr_compound_item(token, index, name, item);
|
||||
exprs.add(item_comp);
|
||||
|
||||
|
||||
if(!token_match(TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
token_expect(TK_CloseBrace);
|
||||
|
||||
|
||||
Ast_Expr *result = ast_expr_compound(pos, 0, exprs);
|
||||
return result;
|
||||
}
|
||||
@@ -165,14 +165,24 @@ parse_optional_type(){
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
function Ast_Block *
|
||||
parse_block(){
|
||||
Ast_Block *result = 0;
|
||||
if(token_match(TK_NewScope)){
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
function Ast_Lambda *
|
||||
parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently
|
||||
// @Todo(Krzosa): Combine this with typespec function parsing
|
||||
Scratch scratch;
|
||||
Array<Ast_Expr *> params = {scratch};
|
||||
// @Note(Krzosa): No need to guard against "()"
|
||||
// @Note(Krzosa): No need to guard against "()"
|
||||
// We needed to lookahead to verify it's a function
|
||||
// and this routine only fires when we have situation
|
||||
// and this routine only fires when we have situation
|
||||
// with at least one parameter
|
||||
for(;;){
|
||||
Token *name = token_expect(TK_Identifier);
|
||||
@@ -180,12 +190,14 @@ parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typesp
|
||||
Ast_Typespec *typespec = parse_typespec();
|
||||
Ast_Expr *param = ast_expr_lambda_param(name, name->intern_val, typespec);
|
||||
params.add(param);
|
||||
|
||||
|
||||
if(!token_match(TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
token_expect(TK_CloseParen);
|
||||
|
||||
//Ast_Block *block = parse_block();
|
||||
Ast_Lambda *result = ast_lambda(token, params, parse_optional_type());
|
||||
return result;
|
||||
}
|
||||
@@ -196,7 +208,7 @@ null_denotation(Token *token){
|
||||
case TK_StringLit : return ast_expr_string(token, token->intern_val);
|
||||
case TK_Identifier: return ast_expr_identifier(token, token->intern_val);
|
||||
case TK_Integer : return ast_expr_integer(token, token->int_val);
|
||||
case TK_BitXor : return ast_expr_unary(token, TK_Dereference, parse_expr());
|
||||
case TK_Pointer : return ast_expr_unary(token, TK_Dereference, parse_expr());
|
||||
case TK_Keyword: {
|
||||
if(token->intern_val == keyword_cast){
|
||||
token_expect(TK_OpenParen);
|
||||
@@ -207,7 +219,7 @@ null_denotation(Token *token){
|
||||
return ast_expr_cast(token, expr, typespec);
|
||||
}
|
||||
else {
|
||||
parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
|
||||
parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
|
||||
return 0;
|
||||
}
|
||||
}break;
|
||||
@@ -216,8 +228,8 @@ null_denotation(Token *token){
|
||||
if(token_match(TK_CloseParen)) return ast_expr_lambda_empty(token);
|
||||
else if(token_is(TK_Identifier) && token_is(TK_Colon, 1)) return parse_lambda(token);
|
||||
else{
|
||||
Ast_Expr *result = parse_expr();
|
||||
token_expect(TK_CloseParen);
|
||||
Ast_Expr *result = parse_expr();
|
||||
token_expect(TK_CloseParen);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -226,18 +238,18 @@ null_denotation(Token *token){
|
||||
}
|
||||
|
||||
function S64
|
||||
left_binding_power(Token_Kind kind){
|
||||
left_binding_power(Token_Kind kind){
|
||||
switch(kind){
|
||||
case TK_Sub: case TK_Add: return 1;
|
||||
case TK_Mul: case TK_Div: return 2;
|
||||
case TK_Sub: case TK_Add: return 1;
|
||||
case TK_Mul: case TK_Div: return 2;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function S64
|
||||
postfix_binding_power(Token_Kind kind){
|
||||
postfix_binding_power(Token_Kind kind){
|
||||
switch(kind){
|
||||
case TK_Increment: case TK_Decrement: case TK_BitXor: case TK_OpenBracket: return 1;
|
||||
case TK_Increment: case TK_Decrement: case TK_Pointer: case TK_OpenBracket: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@@ -259,11 +271,11 @@ parse_expr(S64 rbp){
|
||||
Ast_Expr *left = null_denotation(token);
|
||||
for(;;){
|
||||
token = token_get();
|
||||
|
||||
if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_BitXor || token->kind == TK_OpenBracket)){
|
||||
|
||||
if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_Pointer || token->kind == TK_OpenBracket)){
|
||||
token_next();
|
||||
if(token->kind == TK_OpenBracket){
|
||||
Ast_Expr *index = parse_expr();
|
||||
Ast_Expr *index = parse_expr();
|
||||
left = ast_expr_index(token, left, index);
|
||||
token_expect(TK_CloseBracket);
|
||||
}
|
||||
@@ -273,13 +285,13 @@ parse_expr(S64 rbp){
|
||||
left = ast_expr_unary(token, token->kind, left);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if(rbp < left_binding_power(token->kind)){
|
||||
token = token_next();
|
||||
left = left_denotation(token, left);
|
||||
}
|
||||
else break;
|
||||
|
||||
|
||||
}
|
||||
return left;
|
||||
}
|
||||
@@ -312,11 +324,11 @@ expr_eval(Ast_Expr *expr){
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_PARSER() \
|
||||
Scratch scratch(thread_ctx.scratch);\
|
||||
Parse_Ctx ctx = {}; \
|
||||
ctx.init(scratch, scratch); \
|
||||
pctx = &ctx
|
||||
#define TEST_PARSER() \
|
||||
Scratch scratch(thread_ctx.scratch); \
|
||||
Parse_Ctx ctx = {}; \
|
||||
ctx.init(scratch, scratch); \
|
||||
pctx = &ctx
|
||||
|
||||
function void
|
||||
test_parse_expr(){
|
||||
@@ -329,8 +341,8 @@ test_parse_expr(){
|
||||
exprs.add({"4+5*2"_s, 4+5*2});
|
||||
exprs.add({"4*5+5"_s, 4*5+5});
|
||||
exprs.add({"4+5+5+3"_s, 4+5+5+3});
|
||||
|
||||
Iter(exprs){
|
||||
|
||||
For(exprs){
|
||||
lex_restream(&ctx, it->str, "test_expr"_s);
|
||||
Ast_Expr *result = parse_expr();
|
||||
S64 val = expr_eval(result);
|
||||
@@ -341,12 +353,11 @@ test_parse_expr(){
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parsing declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// [10]*int - Array of 10 pointers to ints
|
||||
function Ast_Typespec *
|
||||
parse_typespec_recurse(){
|
||||
Token *token = token_get();
|
||||
if(token_match(TK_BitXor)){
|
||||
if(token_match(TK_Pointer)){
|
||||
Ast_Typespec *result = parse_typespec_recurse();
|
||||
result = ast_typespec_pointer(token, result);
|
||||
return result;
|
||||
@@ -395,20 +406,20 @@ parse_decl(){
|
||||
Ast_Expr *expr = parse_expr();
|
||||
result = ast_decl_const(name, name->intern_val, expr);
|
||||
}
|
||||
else if(token_match(TK_Colon)){
|
||||
else if(token_match(TK_Colon)){
|
||||
Ast_Typespec *typespec = 0;
|
||||
Ast_Expr *expr = 0;
|
||||
if(!token_is(TK_Assign)) typespec = parse_typespec();
|
||||
if(token_match(TK_Assign)) expr = parse_expr();
|
||||
if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value");
|
||||
|
||||
|
||||
result = ast_decl_var(name, typespec, name->intern_val, expr);
|
||||
}
|
||||
else{
|
||||
Token *token = token_get();
|
||||
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user