implemented call expression parsing
This commit is contained in:
parent
d1b89939ae
commit
37356facc2
6 changed files with 95 additions and 9 deletions
8
lc.c
8
lc.c
|
|
@ -108,6 +108,14 @@ void print_ast(ast_node *node, int depth) {
|
||||||
current = current->expr.unit_node.next;
|
current = current->expr.unit_node.next;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NODE_CALL:
|
||||||
|
printf("Call: %.*s\n", (int)node->expr.call.name_len, node->expr.call.name);
|
||||||
|
current = node->expr.call.parameters;
|
||||||
|
while (current && current->type == NODE_UNIT) {
|
||||||
|
print_ast(current->expr.unit_node.expr, depth + 1);
|
||||||
|
current = current->expr.unit_node.next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case NODE_IF:
|
case NODE_IF:
|
||||||
printf("IfStmt (Fields missing in struct)\n");
|
printf("IfStmt (Fields missing in struct)\n");
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
75
parser.c
75
parser.c
|
|
@ -82,6 +82,74 @@ static void error(parser *p, char *msg)
|
||||||
parser_sync(p);
|
parser_sync(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ast_node *parse_call(parser *p)
|
||||||
|
{
|
||||||
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->type = NODE_CALL;
|
||||||
|
node->expr.call.name = peek(p)->lexeme;
|
||||||
|
node->expr.call.name_len = peek(p)->lexeme_len;
|
||||||
|
advance(p);
|
||||||
|
/* Skip also the opening `(` */
|
||||||
|
advance(p);
|
||||||
|
/* Call without parameters */
|
||||||
|
if (match(p, TOKEN_RPAREN)) {
|
||||||
|
node->expr.call.parameters = NULL;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot arena_start = arena_snapshot(p->allocator);
|
||||||
|
node->expr.call.parameters = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->expr.call.parameters->type = NODE_UNIT;
|
||||||
|
node->expr.call.parameters->expr.unit_node.expr = parse_expression(p);
|
||||||
|
ast_node *tail = node->expr.call.parameters;
|
||||||
|
node->expr.call.param_len = 1;
|
||||||
|
|
||||||
|
/* In this case, there is only one parameter */
|
||||||
|
if (match(p, TOKEN_RPAREN)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match(p, TOKEN_COMMA)) {
|
||||||
|
ast_node *expr = parse_expression(p);
|
||||||
|
if (expr) {
|
||||||
|
while (!match(p, TOKEN_RPAREN)) {
|
||||||
|
if (!match(p, TOKEN_COMMA)) {
|
||||||
|
error(p, "expected `)`.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tail->expr.unit_node.next = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
tail->expr.unit_node.next->expr.unit_node.expr = expr;
|
||||||
|
tail = tail->expr.unit_node.next;
|
||||||
|
tail->type = NODE_UNIT;
|
||||||
|
expr = parse_expression(p);
|
||||||
|
if (!expr) {
|
||||||
|
error(p, "expected `)`.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
node->expr.call.param_len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tail->expr.unit_node.next = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
tail->expr.unit_node.next->expr.unit_node.expr = expr;
|
||||||
|
tail = tail->expr.unit_node.next;
|
||||||
|
tail->type = NODE_UNIT;
|
||||||
|
} else {
|
||||||
|
error(p, "expected expression.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error(p, "expected `)`.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse expressions with the highest precedence. */
|
/* Parse expressions with the highest precedence. */
|
||||||
static ast_node *parse_factor(parser *p)
|
static ast_node *parse_factor(parser *p)
|
||||||
{
|
{
|
||||||
|
|
@ -96,7 +164,12 @@ static ast_node *parse_factor(parser *p)
|
||||||
node->type = NODE_FLOAT;
|
node->type = NODE_FLOAT;
|
||||||
node->expr.flt = parse_float(t->lexeme, t->lexeme_len);
|
node->expr.flt = parse_float(t->lexeme, t->lexeme_len);
|
||||||
return node;
|
return node;
|
||||||
} else if (match(p, TOKEN_IDENTIFIER)) {
|
} else if (match_peek(p, TOKEN_IDENTIFIER)) {
|
||||||
|
/* If a `(` is found after an identifier, it should be a call. */
|
||||||
|
if (p->tokens->next && p->tokens->next->type == TOKEN_LPAREN) {
|
||||||
|
return parse_call(p);
|
||||||
|
}
|
||||||
|
|
||||||
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
node->type = NODE_IDENTIFIER;
|
node->type = NODE_IDENTIFIER;
|
||||||
node->expr.string.start = t->lexeme;
|
node->expr.string.start = t->lexeme;
|
||||||
|
|
|
||||||
13
parser.h
13
parser.h
|
|
@ -52,7 +52,6 @@ typedef struct {
|
||||||
usize type_len;
|
usize type_len;
|
||||||
char *name;
|
char *name;
|
||||||
usize name_len;
|
usize name_len;
|
||||||
usize offset;
|
|
||||||
} member;
|
} member;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -68,12 +67,12 @@ typedef enum {
|
||||||
NODE_STRING,
|
NODE_STRING,
|
||||||
NODE_CHAR,
|
NODE_CHAR,
|
||||||
NODE_CAST,
|
NODE_CAST,
|
||||||
|
NODE_UNARY,
|
||||||
|
NODE_BINARY,
|
||||||
NODE_ARRAY_SUBSCRIPT,
|
NODE_ARRAY_SUBSCRIPT,
|
||||||
NODE_ACCESS,
|
NODE_ACCESS,
|
||||||
NODE_CALL,
|
NODE_CALL,
|
||||||
NODE_POSTFIX,
|
NODE_POSTFIX,
|
||||||
NODE_UNARY,
|
|
||||||
NODE_BINARY,
|
|
||||||
NODE_GOTO,
|
NODE_GOTO,
|
||||||
NODE_BREAK,
|
NODE_BREAK,
|
||||||
NODE_CASE,
|
NODE_CASE,
|
||||||
|
|
@ -84,7 +83,6 @@ typedef enum {
|
||||||
NODE_IF,
|
NODE_IF,
|
||||||
NODE_RETURN,
|
NODE_RETURN,
|
||||||
NODE_COMPOUND,
|
NODE_COMPOUND,
|
||||||
NODE_TYPEDEF,
|
|
||||||
NODE_ENUM,
|
NODE_ENUM,
|
||||||
NODE_STRUCT,
|
NODE_STRUCT,
|
||||||
NODE_UNION,
|
NODE_UNION,
|
||||||
|
|
@ -137,6 +135,13 @@ typedef struct _ast_node {
|
||||||
struct _ast_node *expr;
|
struct _ast_node *expr;
|
||||||
struct _ast_node *next;
|
struct _ast_node *next;
|
||||||
} unit_node;
|
} unit_node;
|
||||||
|
struct {
|
||||||
|
/* This should be a list of unit_node */
|
||||||
|
struct _ast_node *parameters;
|
||||||
|
usize param_len;
|
||||||
|
char *name;
|
||||||
|
usize name_len;
|
||||||
|
} call;
|
||||||
} expr;
|
} expr;
|
||||||
} ast_node;
|
} ast_node;
|
||||||
|
|
||||||
|
|
|
||||||
2
test.c
2
test.c
|
|
@ -1 +1 @@
|
||||||
x.y
|
x(4, 5)
|
||||||
|
|
|
||||||
4
utils.c
4
utils.c
|
|
@ -97,9 +97,9 @@ void *arena_alloc(arena *a, usize size) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot arena_snapshot(arena a)
|
snapshot arena_snapshot(arena *a)
|
||||||
{
|
{
|
||||||
return a.position;
|
return a->position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arena_reset_to_snapshot(arena *a, snapshot s)
|
void arena_reset_to_snapshot(arena *a, snapshot s)
|
||||||
|
|
|
||||||
2
utils.h
2
utils.h
|
|
@ -43,7 +43,7 @@ arena arena_init(usize size);
|
||||||
* does not have enough memory to allocate the requested space
|
* does not have enough memory to allocate the requested space
|
||||||
*/
|
*/
|
||||||
void *arena_alloc(arena *a, usize size);
|
void *arena_alloc(arena *a, usize size);
|
||||||
snapshot arena_snapshot(arena a);
|
snapshot arena_snapshot(arena *a);
|
||||||
void arena_reset_to_snapshot(arena *a, snapshot s);
|
void arena_reset_to_snapshot(arena *a, snapshot s);
|
||||||
void arena_reset(arena *a);
|
void arena_reset(arena *a);
|
||||||
/* This call should never fail, also, do we even care if it does? */
|
/* This call should never fail, also, do we even care if it does? */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue