Compile string, working on scopes
This commit is contained in:
126
new_parse.cpp
126
new_parse.cpp
@@ -1,4 +1,30 @@
|
||||
|
||||
function void
|
||||
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 + 1);
|
||||
|
||||
// @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();
|
||||
}
|
||||
|
||||
function Token *
|
||||
token_get(S64 i = 0){
|
||||
i += pctx->token_iter;
|
||||
@@ -47,32 +73,6 @@ token_match_keyword(Intern_String string){
|
||||
return 0;
|
||||
}
|
||||
|
||||
function void
|
||||
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 + 1);
|
||||
|
||||
// @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();
|
||||
}
|
||||
|
||||
function Token *
|
||||
token_expect(Token_Kind kind){
|
||||
Token *token = token_get();
|
||||
@@ -81,14 +81,17 @@ token_expect(Token_Kind kind){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @note: right now we check if on downscope there is a end of file
|
||||
// not sure if this is the right approach codewise but the fact
|
||||
// that end of file is treated as end of scope feels intuitive
|
||||
function Token *
|
||||
token_is_scope(Token_Kind scope){
|
||||
assert(scope == OPEN_SCOPE || scope == CLOSE_SCOPE || scope == SAME_SCOPE);
|
||||
Token *token = token_get();
|
||||
if(token->kind == TK_NewLine){
|
||||
if (scope == OPEN_SCOPE && token->indent > pctx->indent) return token;
|
||||
else if(scope == CLOSE_SCOPE && token->indent < pctx->indent) return token;
|
||||
else if(scope == SAME_SCOPE && token->indent == pctx->indent) return token;
|
||||
if(token->kind == TK_NewLine || token->kind == TK_End){
|
||||
if (scope == OPEN_SCOPE && token->indent > pctx->indent) return token;
|
||||
else if(scope == SAME_SCOPE && token->indent == pctx->indent) return token;
|
||||
else if((scope == CLOSE_SCOPE) && ((token->indent < pctx->indent) || (token->kind == TK_End))) return token;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -104,10 +107,10 @@ function Token *
|
||||
token_expect_scope(Token_Kind scope){
|
||||
assert(scope == OPEN_SCOPE || scope == CLOSE_SCOPE || scope == SAME_SCOPE);
|
||||
Token *token = token_get();
|
||||
if(token->kind == TK_NewLine){
|
||||
if (scope == OPEN_SCOPE && token->indent > pctx->indent) return token;
|
||||
else if(scope == CLOSE_SCOPE && token->indent < pctx->indent) return token;
|
||||
else if(scope == SAME_SCOPE && token->indent == pctx->indent) return token;
|
||||
if(token->kind == TK_NewLine || token->kind == TK_End){
|
||||
if (scope == OPEN_SCOPE && token->indent > pctx->indent) return token_next();
|
||||
else if(scope == SAME_SCOPE && token->indent == pctx->indent) return token_next();
|
||||
else if((scope == CLOSE_SCOPE) && ((token->indent < pctx->indent) || (token->kind == TK_End))) return token_next();
|
||||
else parsing_error(token, "Expected a scope of kind [%s]", token_kind_string(scope));
|
||||
}
|
||||
parsing_error(token, "Expected Scope[%s] got instead: [%s]", token_kind_string(scope).str, token_kind_string(token->kind).str);
|
||||
@@ -220,30 +223,27 @@ parse_block(){
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
function Ast_Lambda *
|
||||
parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently
|
||||
parse_lambda(Token *token, B32 is_typespec = false){
|
||||
Scratch scratch;
|
||||
Array<Ast_Lambda_Arg *> params = {scratch};
|
||||
// @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
|
||||
// with at least one parameter
|
||||
for(;;){
|
||||
Token *name = token_expect(TK_Identifier);
|
||||
token_expect(TK_Colon);
|
||||
Ast_Typespec *typespec = parse_typespec();
|
||||
Ast_Lambda_Arg *param = ast_expr_lambda_arg(name, name->intern_val, typespec);
|
||||
params.add(param);
|
||||
if(!token_is(TK_CloseParen)){
|
||||
for(;;){
|
||||
Token *name = token_expect(TK_Identifier);
|
||||
token_expect(TK_Colon);
|
||||
Ast_Typespec *typespec = parse_typespec();
|
||||
Ast_Lambda_Arg *param = ast_expr_lambda_arg(name, name->intern_val, typespec);
|
||||
params.add(param);
|
||||
|
||||
if(!token_match(TK_Comma)){
|
||||
break;
|
||||
if(!token_match(TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
token_expect(TK_CloseParen);
|
||||
|
||||
Ast_Typespec *ret = parse_optional_type();
|
||||
Ast_Block *block = parse_block();
|
||||
Ast_Block *block = is_typespec ? 0 : parse_block();
|
||||
Ast_Lambda *result = ast_lambda(token, params, ret, block);
|
||||
return result;
|
||||
}
|
||||
@@ -271,7 +271,7 @@ null_denotation(Token *token){
|
||||
}break;
|
||||
case TK_OpenBrace: return parse_expr_compound();
|
||||
case TK_OpenParen: {
|
||||
if(token_match(TK_CloseParen)) return ast_expr_lambda_empty(token);
|
||||
if (token_is(TK_CloseParen)) return parse_lambda(token);
|
||||
else if(token_is(TK_Identifier) && token_is(TK_Colon, 1)) return parse_lambda(token);
|
||||
else{
|
||||
Ast_Expr *result = parse_expr();
|
||||
@@ -342,32 +342,6 @@ parse_expr(S64 rbp){
|
||||
return left;
|
||||
}
|
||||
|
||||
#define TEST_PARSER() \
|
||||
Scratch scratch(thread_ctx.scratch); \
|
||||
Parse_Ctx ctx = {}; \
|
||||
ctx.init(scratch, scratch); \
|
||||
pctx = &ctx
|
||||
|
||||
function void
|
||||
test_parse_expr(){
|
||||
TEST_PARSER();
|
||||
struct Test{String str;S64 val;};
|
||||
// Array<Test> exprs = {scratch};
|
||||
//exprs.add({"thing[1][2][3]"_s, 0});
|
||||
// exprs.add({"4++++--"_s, 5});
|
||||
// exprs.add({"(4+5)*2"_s, (4+5)*2});
|
||||
// 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});
|
||||
|
||||
// For(exprs){
|
||||
// lex_restream(&ctx, it->str, "test_expr"_s);
|
||||
// Ast_Expr *result = parse_expr();
|
||||
// S64 val = expr_eval(result);
|
||||
// assert(val == it->val);
|
||||
// }
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parsing declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user