Added lambda expressions, lambda types, no body yet
This commit is contained in:
146
new_parse.cpp
146
new_parse.cpp
@@ -21,8 +21,8 @@ token_next(){
|
||||
}
|
||||
|
||||
function Token *
|
||||
token_is(Token_Kind kind){
|
||||
Token *token = token_get();
|
||||
token_is(Token_Kind kind, S64 lookahead = 0){
|
||||
Token *token = token_get(lookahead);
|
||||
if(token->kind == kind){
|
||||
return token;
|
||||
}
|
||||
@@ -158,12 +158,45 @@ parse_expr_compound(){
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Typespec *
|
||||
parse_optional_type(){
|
||||
Ast_Typespec *result = 0;
|
||||
if(token_match(TK_Colon)) result = parse_typespec();
|
||||
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 "()"
|
||||
// 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_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_Lambda *result = ast_lambda(token, params, parse_optional_type());
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Expr *
|
||||
parse_expr_nud(Token *token){
|
||||
null_denotation(Token *token){
|
||||
switch(token->kind){
|
||||
case TK_StringLit: return ast_expr_string(token, token->intern_val);
|
||||
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_Integer : return ast_expr_integer(token, token->int_val);
|
||||
case TK_BitXor : return ast_expr_unary(token, TK_Dereference, parse_expr());
|
||||
case TK_Keyword: {
|
||||
if(token->intern_val == keyword_cast){
|
||||
token_expect(TK_OpenParen);
|
||||
@@ -179,22 +212,41 @@ parse_expr_nud(Token *token){
|
||||
}
|
||||
}break;
|
||||
case TK_OpenBrace: return parse_expr_compound();
|
||||
case TK_OpenParen: {Ast_Expr *result = parse_expr(); token_expect(TK_CloseParen); return result;}
|
||||
case TK_OpenParen: {
|
||||
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);
|
||||
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){
|
||||
S64 result = pctx->pt[kind];
|
||||
return result;
|
||||
left_binding_power(Token_Kind kind){
|
||||
switch(kind){
|
||||
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){
|
||||
switch(kind){
|
||||
case TK_Increment: case TK_Decrement: case TK_BitXor: case TK_OpenBracket: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function Ast_Expr *
|
||||
parse_expr_led(Token *op, Ast_Expr *left){
|
||||
left_denotation(Token *op, Ast_Expr *left){
|
||||
enum{ Left_Associative, Right_Associative };
|
||||
S64 assoc = Left_Associative;
|
||||
Ast_Expr *right = parse_expr(op_precedence(op->kind) - assoc);
|
||||
Ast_Expr *right = parse_expr(left_binding_power(op->kind) - assoc);
|
||||
switch(op->kind){
|
||||
case TK_Add: case TK_Mul: case TK_Sub: case TK_Div: return ast_expr_binary(left, right, op);
|
||||
default: parsing_error(op, "Unexpected token of kind: [%s] in expression", token_kind_string(op->kind).str); return 0;
|
||||
@@ -204,10 +256,30 @@ parse_expr_led(Token *op, Ast_Expr *left){
|
||||
function Ast_Expr *
|
||||
parse_expr(S64 rbp){
|
||||
Token *token = token_next();
|
||||
Ast_Expr *left = parse_expr_nud(token);
|
||||
while(rbp < op_precedence(token_get()->kind)){
|
||||
token = token_next();
|
||||
left = parse_expr_led(token, left);
|
||||
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)){
|
||||
token_next();
|
||||
if(token->kind == TK_OpenBracket){
|
||||
Ast_Expr *index = parse_expr();
|
||||
left = ast_expr_index(token, left, index);
|
||||
token_expect(TK_CloseBracket);
|
||||
}
|
||||
else{
|
||||
if(token->kind == TK_Increment) token->kind = TK_PostIncrement;
|
||||
else if(token->kind == TK_Decrement) token->kind = TK_PostDecrement;
|
||||
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;
|
||||
}
|
||||
@@ -215,8 +287,16 @@ parse_expr(S64 rbp){
|
||||
function S64
|
||||
expr_eval(Ast_Expr *expr){
|
||||
switch(expr->kind){
|
||||
case AK_Expr_Int: return expr->int_val;
|
||||
case AK_Expr_Binary : {
|
||||
case AST_INT: return expr->int_val;
|
||||
case AST_UNARY:{
|
||||
S64 value = expr_eval(expr->unary.expr);
|
||||
switch(expr->unary.op){
|
||||
case TK_PostDecrement: return value - 1;
|
||||
case TK_PostIncrement: return value + 1;
|
||||
default: invalid_codepath;
|
||||
}
|
||||
}break;
|
||||
case AST_BINARY : {
|
||||
S64 left = expr_eval(expr->binary.left);
|
||||
S64 right = expr_eval(expr->binary.right);
|
||||
switch(expr->binary.op){
|
||||
@@ -243,6 +323,8 @@ 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});
|
||||
@@ -259,36 +341,12 @@ test_parse_expr(){
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parsing declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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)){
|
||||
if(token_match(TK_BitXor)){
|
||||
Ast_Typespec *result = parse_typespec_recurse();
|
||||
result = ast_typespec_pointer(token, result);
|
||||
return result;
|
||||
@@ -301,8 +359,8 @@ parse_typespec_recurse(){
|
||||
return result;
|
||||
}
|
||||
else if(token_match(TK_OpenParen)){
|
||||
Ast_Typespec *result = parse_typespec_function(token);
|
||||
return result;
|
||||
Ast_Lambda *result = parse_lambda(token, true);
|
||||
return ast_typespec_lambda(token, result);
|
||||
}
|
||||
else if(token_match(TK_Identifier)){
|
||||
Ast_Typespec *result = ast_typespec_name(token, token->intern_val);
|
||||
|
||||
Reference in New Issue
Block a user