Named function args

This commit is contained in:
Krzosa Karol
2022-05-06 15:56:22 +02:00
parent 7e3eefda57
commit 76a8cc779c
5 changed files with 543 additions and 291 deletions

View File

@@ -110,13 +110,15 @@ atom_expr = Int
| String
| Identifier
| 'cast' '(' typespec ',' expr ')'
| 'size_type' '(' typespec ')'
| 'size_expr' '(' expr ')'
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
unary_expr = unary ? unary_expr : atom_expr
mul_expr = atom_expr (mul atom_expr)*
add_expr = mul_expr (add mul_expr)*
compare_expr = add_expr (compare add_expr)*
logical_expr = compare_expr (logical compare_expr)*
ternary_expr = logical_expr ('?' ternary_expr ':' ternary_expr)?
logical_expr = add_expr (logical add_expr)*
compare_expr = logical_expr (compare logical_expr)*
ternary_expr = compare_expr ('?' ternary_expr ':' ternary_expr)?
expr = logical_expr
*/
function Expr *parse_expr(Parser *p);
@@ -167,6 +169,51 @@ token_is_postfix(Parser *p){
return result;
}
function Expr_Compound_Field *
parse_expr_compound(Parser *p){
Token *token = token_get(p);
Expr_Compound_Field *result = 0;
if(token_match(p, TK_OpenBracket)){
Expr *index = parse_expr(p);
token_expect(p, TK_CloseBracket);
token_expect(p, TK_Assign);
Expr *expr = parse_expr(p);
result = expr_compound_index(p->arena, token, index, expr);
}
else{
Expr *expr = parse_expr(p);
if((token = token_match(p, TK_Assign))){
if(expr->kind != EK_Identifier){
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);
}
}
return result;
}
function Expr_Compound_Field *
parse_expr_function_argument(Parser *p){
Token *token = token_get(p);
Expr_Compound_Field *result = 0;
Expr *expr1 = parse_expr(p);
if(token_match(p, TK_Assign)){
if(expr1->kind != EK_Identifier){
parser_push_error(p, token, "Failed to parse named function argument, required identifier as left value");
}
Expr *expr2 = parse_expr(p);
result = expr_compound_named(p->arena, token, expr1->intern_val, expr2);
}
else{
result = expr_compound_default(p->arena, token, expr1);
}
return result;
}
function Expr *
parse_expr_postfix(Parser *p){
Expr *left = parse_expr_atom(p);
@@ -180,10 +227,10 @@ parse_expr_postfix(Parser *p){
else if((token = token_match(p, TK_OpenParen))){
left = expr_call(p->arena, token, left);
if(!token_is(p, TK_CloseParen)){
expr_call_push(left, parse_expr(p));
while(token_match(p, TK_Comma)){
expr_call_push(left, parse_expr(p));
}
do {
Expr_Compound_Field *field = parse_expr_function_argument(p);
expr_call_push(left, field);
} while(token_match(p, TK_Comma));
}
token_expect(p, TK_CloseParen);
}
@@ -263,24 +310,6 @@ parse_expr_add(Parser *p){
return left;
}
function B32
token_is_compare(Parser *p){
Token *token = token_get(p);
B32 result = token->kind >= TK_FirstCompare && token->kind <= TK_LastCompare;
return result;
}
function Expr *
parse_expr_compare(Parser *p){
Expr *left = parse_expr_add(p);
while(token_is_compare(p)){
Token *op = token_next(p);
Expr *right = parse_expr_add(p);
left = expr_binary(p->arena, op, left, right);
}
return left;
}
function B32
token_is_logical(Parser *p){
Token *token = token_get(p);
@@ -290,10 +319,28 @@ token_is_logical(Parser *p){
function Expr *
parse_expr_logical(Parser *p){
Expr *left = parse_expr_compare(p);
Expr *left = parse_expr_add(p);
while(token_is_logical(p)){
Token *op = token_next(p);
Expr *right = parse_expr_compare(p);
Expr *right = parse_expr_add(p);
left = expr_binary(p->arena, op, left, right);
}
return left;
}
function B32
token_is_compare(Parser *p){
Token *token = token_get(p);
B32 result = token->kind >= TK_FirstCompare && token->kind <= TK_LastCompare;
return result;
}
function Expr *
parse_expr_compare(Parser *p){
Expr *left = parse_expr_logical(p);
while(token_is_compare(p)){
Token *op = token_next(p);
Expr *right = parse_expr_logical(p);
left = expr_binary(p->arena, op, left, right);
}
return left;
@@ -301,7 +348,7 @@ parse_expr_logical(Parser *p){
function Expr *
parse_expr_ternary(Parser *p){
Expr *cond = parse_expr_logical(p);
Expr *cond = parse_expr_compare(p);
Token *token = 0;
if((token = token_match(p, TK_Question))){
Expr *on_true = parse_expr_ternary(p);
@@ -321,11 +368,32 @@ parse_expr(Parser *p){
//-----------------------------------------------------------------------------
// Test code
//-----------------------------------------------------------------------------
function void expr_print(Expr *expr);
function void
token_print(Token *token){
printf("%.*s", (S32)token->len, token->str);
}
function void
expr_compound_print(Expr_Compound_Field *field){
switch(field->kind){
case COMPOUND_Default: {
expr_print(field->init);
}break;
case COMPOUND_Named: {
printf("[%s] = ", field->name.s.str);
expr_print(field->init);
}break;
case COMPOUND_Index: {
printf("[");
expr_print(field->index);
printf("] = ");
expr_print(field->init);
}break;
default: invalid_codepath;
}
}
function void
expr_print(Expr *expr){
switch(expr->kind) {
@@ -333,15 +401,24 @@ expr_print(Expr *expr){
token_print(expr->token);
} break;
case EK_Sizeof:{
printf("sizeof(");
if(expr->size_of.kind == SIZEOF_Expr){
expr_print(expr->size_of.expr);
}
else{
assert(expr->size_of.kind == SIZEOF_Type);
//print_typespec(expr->size_of.type);
case EK_SizeExpr:{
printf("size_expr(");
expr_print(expr->size_expr.expr);
printf(")");
}break;
case EK_Compound:{
// typespec_print(p);
printf("{");
for(Expr_Compound_Field *n = expr->compound.first; n; n=n->next){
expr_compound_print(n);
if(n!=expr->compound.last) printf(",");
}
printf("}");
} break;
case EK_SizeType:{
printf("size_type(");
printf(")");
}break;
@@ -407,8 +484,8 @@ expr_print(Expr *expr){
case EK_Call:{
expr_print(expr->call.atom);
printf("(");
for(Expr *n = expr->call.first; n; n=n->next){
expr_print(n);
for(Expr_Compound_Field *n = expr->call.first; n; n=n->next){
expr_compound_print(n);
if(n!=expr->call.last) printf(",");
}
printf(")");
@@ -474,13 +551,14 @@ parse_test(){
String test_case = lit("32+52-242*2/424%5-23"
" 1<<5>>6<<2 "
" 5*(4/3)*(2+5) "
" 0&1 == 1&0 "
" 1&&5*3 "
" 1&&5||0 "
" 1>5>=5==0 "
" 1>5 ? 1 : 2 "
" !!!!!1 "
" ~~1 + -!2 "
" 1 + ++Thing[12]++ + ++Thing[12].expr + --Not_Thing[156](Thing) + test_func(func1, func2, func3)"
" 1 + ++Thing[12]++ + ++Thing[12].expr + --Not_Thing[156](Thing) + test_func(asd=func1, af=func2, gg=func3)"
);
Parser parser = {
.tokens = lex_stream(scratch, test_case, lit("expr_test")),
@@ -493,6 +571,7 @@ parse_test(){
(32+52-242*2/424%5-23),
(((1<<5)>>6)<<2),
5*(4/3)*(2+5),
(0&1) == (1&0),
1&&(t*3),
(1&&t)||0,
1>t>=t==0,