Starting from scratch on smaller scale, typechecking global and constant variables, compound expressions for arrays
This commit is contained in:
205
new_parse.cpp
205
new_parse.cpp
@@ -1,22 +1,22 @@
|
||||
|
||||
function Token *
|
||||
token_get(S64 i = 0){ Get_Ctx(Parse_Ctx);
|
||||
i += ctx->token_iter;
|
||||
if(i >= ctx->tokens.len){
|
||||
return &ctx->empty_token;
|
||||
token_get(S64 i = 0){
|
||||
i += pctx->token_iter;
|
||||
if(i >= pctx->tokens.len){
|
||||
return &pctx->empty_token;
|
||||
}
|
||||
Token *result = &ctx->tokens[i];
|
||||
Token *result = &pctx->tokens[i];
|
||||
if(result->kind == TK_NewLine){
|
||||
ctx->indent = result->indent;
|
||||
pctx->indent = result->indent;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function Token *
|
||||
token_next(){ Get_Ctx(Parse_Ctx);
|
||||
token_next(){
|
||||
Token *token = token_get();
|
||||
ctx->token_iter++;
|
||||
pctx->token_iter++;
|
||||
return token;
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ token_match_keyword(Intern_String string){
|
||||
|
||||
function void
|
||||
parsing_error(Token *token, const char *str, ...){
|
||||
Set_Scratch();
|
||||
STRING_FMT(imp_get(), str, string);
|
||||
Scratch scratch;
|
||||
STRING_FMT(scratch, str, string);
|
||||
|
||||
// @Note(Krzosa): Print nice error message
|
||||
printf("\nError: %s", string.str);
|
||||
@@ -122,6 +122,41 @@ Compound literals
|
||||
- { }
|
||||
*/
|
||||
function Ast_Expr *parse_expr(S64 rbp = 0);
|
||||
function Ast_Typespec *parse_typespec();
|
||||
|
||||
function Ast_Expr *
|
||||
parse_expr_compound(){
|
||||
Scratch scratch;
|
||||
Token *pos = token_get();
|
||||
Array<Ast_Expr *> exprs = {scratch};
|
||||
while(!token_is(TK_CloseBrace)){
|
||||
Token *token = token_get();
|
||||
Ast_Expr *index = 0;
|
||||
Ast_Expr *name = 0;
|
||||
if(token_match(TK_OpenBracket)){
|
||||
index = parse_expr();
|
||||
token_expect(TK_CloseBracket);
|
||||
token_expect(TK_Assign);
|
||||
}
|
||||
else if(token_is(TK_Identifier)){
|
||||
token = token_next();
|
||||
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;
|
||||
}
|
||||
|
||||
function Ast_Expr *
|
||||
parse_expr_nud(Token *token){
|
||||
@@ -129,14 +164,29 @@ parse_expr_nud(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_Keyword: {
|
||||
if(token->intern_val == keyword_cast){
|
||||
token_expect(TK_OpenParen);
|
||||
Ast_Expr *expr = parse_expr();
|
||||
token_expect(TK_Colon);
|
||||
Ast_Typespec *typespec = parse_typespec();
|
||||
token_expect(TK_CloseParen);
|
||||
return ast_expr_cast(token, expr, typespec);
|
||||
}
|
||||
else {
|
||||
parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
|
||||
return 0;
|
||||
}
|
||||
}break;
|
||||
case TK_OpenBrace: return parse_expr_compound();
|
||||
case TK_OpenParen: {Ast_Expr *result = parse_expr(); token_expect(TK_CloseParen); return result;}
|
||||
default: parsing_error(token, "Unexpected token of kind: [%s] in expression", token_kind_string(token->kind).str); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function S64
|
||||
op_precedence(Token_Kind kind){ Get_Ctx(Parse_Ctx);
|
||||
S64 result = ctx->pt[kind];
|
||||
op_precedence(Token_Kind kind){
|
||||
S64 result = pctx->pt[kind];
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -182,23 +232,23 @@ expr_eval(Ast_Expr *expr){
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_PARSER() \
|
||||
Set_Scratch(); \
|
||||
Parse_Ctx ctx = {}; \
|
||||
ctx.init(); \
|
||||
Set_Ctx(&ctx, Parse_Ctx_ID)
|
||||
#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 = {};
|
||||
Array<Test> exprs = {scratch};
|
||||
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,it,i){
|
||||
Iter(exprs){
|
||||
lex_restream(&ctx, it->str, "test_expr"_s);
|
||||
Ast_Expr *result = parse_expr();
|
||||
S64 val = expr_eval(result);
|
||||
@@ -209,38 +259,115 @@ test_parse_expr(){
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parsing declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
function Ast_Decl *
|
||||
parse_decl(){Get_Ctx(Parse_Ctx);
|
||||
Ast_Decl *result = 0;
|
||||
Token *token = token_match(TK_Identifier);
|
||||
if(token){
|
||||
if(token_match(TK_ColonAssign)){
|
||||
if(ctx->indent != 0)
|
||||
parsing_error(token, "Top level declarations shouldn't be indented");
|
||||
|
||||
Ast_Expr *expr = parse_expr();
|
||||
result = ast_decl_var(token, 0, token->intern_val, expr);
|
||||
function Ast_Typespec *
|
||||
parse_optional_type(){
|
||||
Ast_Typespec *result = 0;
|
||||
if(token_match(TK_Colon)) result = parse_typespec();
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Typespec *
|
||||
parse_typespec_function(Token *token){
|
||||
Scratch scratch;
|
||||
Array<Ast_Typespec *> args = {scratch};
|
||||
if(!token_is(TK_CloseParen)) {
|
||||
for(;;) {
|
||||
args.add(parse_typespec());
|
||||
if(!token_match(TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
else parsing_error(token, "Encountered unexpected token while parsing a top level declarations");
|
||||
}
|
||||
token_expect(TK_CloseParen);
|
||||
Ast_Typespec *ret = parse_optional_type();
|
||||
Ast_Typespec *result = ast_typespec_func(token, ret, args);
|
||||
return result;
|
||||
}
|
||||
|
||||
// [10]*int - Array of 10 pointers to ints
|
||||
function Ast_Typespec *
|
||||
parse_typespec_recurse(){
|
||||
Token *token = token_get();
|
||||
if(token_match(TK_Mul)){
|
||||
Ast_Typespec *result = parse_typespec_recurse();
|
||||
result = ast_typespec_pointer(token, result);
|
||||
return result;
|
||||
}
|
||||
else if(token_match(TK_OpenBracket)){
|
||||
Ast_Expr *expr = parse_expr();
|
||||
token_expect(TK_CloseBracket);
|
||||
Ast_Typespec *result = parse_typespec_recurse();
|
||||
result = ast_typespec_array(token, result, expr);
|
||||
return result;
|
||||
}
|
||||
else if(token_match(TK_OpenParen)){
|
||||
Ast_Typespec *result = parse_typespec_function(token);
|
||||
return result;
|
||||
}
|
||||
else if(token_match(TK_Identifier)){
|
||||
Ast_Typespec *result = ast_typespec_name(token, token->intern_val);
|
||||
return result;
|
||||
}
|
||||
else{
|
||||
parsing_error(token, "Failed to parse type, unexpected token of kind", token_kind_string(token->kind).str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function Ast_Typespec *
|
||||
parse_typespec(){
|
||||
Ast_Typespec *result = parse_typespec_recurse();
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Expr *
|
||||
parse_assign_expr(){
|
||||
Ast_Expr *result = 0;
|
||||
if(token_match(TK_Assign)) result = parse_expr();
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Decl *
|
||||
parse_decl(){
|
||||
Ast_Decl *result = 0;
|
||||
if(token_is(TK_Identifier)){
|
||||
if(pctx->indent != 0) parsing_error(token_get(), "Top level declarations shouldn't be indented");
|
||||
Token *name = token_next();
|
||||
if(token_match(TK_DoubleColon)){ // Constant
|
||||
Ast_Expr *expr = parse_expr();
|
||||
result = ast_decl_const(name, name->intern_val, expr);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
function Ast_Package *
|
||||
parse_file(){
|
||||
Ast_Package *result = ast_package(token_get(), token_get()->file);
|
||||
Scratch scratch;
|
||||
Token *token = token_get();
|
||||
Array<Ast_Decl *>decls = {scratch};
|
||||
while(!token_is(TK_End)){
|
||||
while(token_match(TK_NewLine));
|
||||
Ast_Decl *decl = parse_decl();
|
||||
if(!decl) break;
|
||||
result->decls.add(decl);
|
||||
decls.add(decl);
|
||||
}
|
||||
Ast_Package *result = ast_package(token, token->file, decls);
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
test_parse_decl(){
|
||||
TEST_PARSER();
|
||||
lex_restream(&ctx, "thing := 24252\nanother_thing := \"string\"\n\nref := thing"_s, "test_parse_decl"_s);
|
||||
Ast_Package *result = parse_file();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user