completed for loop parsing
This commit is contained in:
parent
0015c2b81d
commit
cb021716ef
4 changed files with 146 additions and 87 deletions
9
lc.c
9
lc.c
|
|
@ -163,14 +163,9 @@ void print_ast(ast_node *node, int depth) {
|
||||||
break;
|
break;
|
||||||
case NODE_FOR:
|
case NODE_FOR:
|
||||||
printf("For:\n");
|
printf("For:\n");
|
||||||
print_ast(node->expr.fr.range, depth + 1);
|
print_ast(node->expr.fr.slices, depth + 1);
|
||||||
print_ast(node->expr.fr.array, depth + 1);
|
print_ast(node->expr.fr.captures, depth + 1);
|
||||||
print_indent(depth + 1);
|
print_indent(depth + 1);
|
||||||
printf("Range capture: %.*s\n", node->expr.fr.rangeCaptureLen, node->expr.fr.rangeCapture);
|
|
||||||
if (node->expr.fr.arrayCapture) {
|
|
||||||
print_indent(depth + 1);
|
|
||||||
printf("Array capture: %.*s\n", node->expr.fr.arrayCaptureLen, node->expr.fr.arrayCapture);
|
|
||||||
}
|
|
||||||
print_ast(node->expr.fr.body, depth + 1);
|
print_ast(node->expr.fr.body, depth + 1);
|
||||||
break;
|
break;
|
||||||
case NODE_RANGE:
|
case NODE_RANGE:
|
||||||
|
|
|
||||||
197
parser.c
197
parser.c
|
|
@ -182,6 +182,24 @@ static ast_node *parse_factor(parser *p)
|
||||||
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
node->type = NODE_INTEGER;
|
node->type = NODE_INTEGER;
|
||||||
node->expr.integer = parse_int(t->lexeme, t->lexeme_len);
|
node->expr.integer = parse_int(t->lexeme, t->lexeme_len);
|
||||||
|
if (match(p, TOKEN_DOUBLE_DOT)) {
|
||||||
|
ast_node *range = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
range->type = NODE_RANGE;
|
||||||
|
range->expr.binary.left = node;
|
||||||
|
range->expr.binary.operator = OP_PLUS;
|
||||||
|
snapshot snap = arena_snapshot(p->allocator);
|
||||||
|
ast_node *end = parse_factor(p);
|
||||||
|
if (!end) {
|
||||||
|
range->expr.binary.right = NULL;
|
||||||
|
} else if (end->type != NODE_INTEGER) {
|
||||||
|
arena_reset_to_snapshot(p->allocator, snap);
|
||||||
|
error(p, "expected integer.");
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
range->expr.binary.right = end;
|
||||||
|
}
|
||||||
|
return range;
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
else if (match(p, TOKEN_FLOAT))
|
else if (match(p, TOKEN_FLOAT))
|
||||||
|
|
@ -510,77 +528,138 @@ static ast_node *parse_compound(parser *p)
|
||||||
return compound;
|
return compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ast_node *parse_double_dot(parser* p) {
|
|
||||||
ast_node* begin = parse_expression(p);
|
|
||||||
if (!begin || (begin->type != NODE_INTEGER && begin->type != NODE_BINARY && begin->type != NODE_UNARY)) {
|
|
||||||
error(p, "Invalid begin range operator.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (!match(p, TOKEN_DOUBLE_DOT)) {
|
|
||||||
error(p, "Expected `..`.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ast_node* node = arena_alloc(p->allocator, sizeof(ast_node));
|
|
||||||
node->type = NODE_RANGE;
|
|
||||||
node->expr.binary.left = begin;
|
|
||||||
node->expr.binary.operator = OP_PLUS; // Always adding 1
|
|
||||||
if (p->tokens->type != TOKEN_INTEGER) {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
ast_node* end = parse_expression(p);
|
|
||||||
if (!end || (end->type != NODE_INTEGER && end->type != NODE_BINARY && end->type != NODE_UNARY)) {
|
|
||||||
error(p, "Invalid end range operator.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
node->expr.binary.right = end;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ast_node *parse_for(parser *p)
|
static ast_node *parse_for(parser *p)
|
||||||
{
|
{
|
||||||
advance(p);
|
advance(p);
|
||||||
ast_node* node = arena_alloc(p->allocator, sizeof(ast_node));
|
ast_node* node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
node->type = NODE_FOR;
|
node->type = NODE_FOR;
|
||||||
ast_node* range = parse_double_dot(p);
|
|
||||||
node->expr.fr.range = range;
|
snapshot arena_start = arena_snapshot(p->allocator);
|
||||||
if (p->tokens->type != TOKEN_RPAREN) {
|
node->expr.fr.slices = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
if (!match(p, TOKEN_COMMA)) {
|
node->expr.fr.slices->type = NODE_UNIT;
|
||||||
error(p, "Expected `,` seperating for parameters\n");
|
node->expr.fr.slices->expr.unit_node.expr = parse_expression(p);
|
||||||
return NULL;
|
ast_node *tail = node->expr.fr.slices;
|
||||||
|
node->expr.fr.slice_len = 1;
|
||||||
|
|
||||||
|
/* In this case, there is only one slice. */
|
||||||
|
if (match(p, TOKEN_RPAREN))
|
||||||
|
{
|
||||||
|
goto parse_captures;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.fr.slice_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;
|
||||||
}
|
}
|
||||||
ast_node* array = parse_expression(p);
|
else
|
||||||
node->expr.fr.array = array;
|
{
|
||||||
}
|
error(p, "expected expression.");
|
||||||
if (!match(p, TOKEN_RPAREN)) {
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
error(p, "Expected `)` to close for range\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (p->tokens->type != TOKEN_PIPE) {
|
|
||||||
goto parseBody;
|
|
||||||
}
|
|
||||||
advance(p);
|
|
||||||
const char* rangeCapture = p->tokens->lexeme;
|
|
||||||
node->expr.fr.rangeCapture = rangeCapture;
|
|
||||||
node->expr.fr.rangeCaptureLen = p->tokens->lexeme_len;
|
|
||||||
if (!match(p, TOKEN_IDENTIFIER)) {
|
|
||||||
error(p, "Expected range capture to be an identifier\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (p->tokens->type == TOKEN_COMMA) {
|
|
||||||
advance(p);
|
|
||||||
const char* arrayCapture = p->tokens->lexeme;
|
|
||||||
node->expr.fr.arrayCapture = arrayCapture;
|
|
||||||
node->expr.fr.arrayCaptureLen = p->tokens->lexeme_len;
|
|
||||||
if (!match(p, TOKEN_IDENTIFIER)) {
|
|
||||||
error(p, "Expected array capture to be an identifier\n");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error(p, "expected `)`.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_captures:
|
||||||
|
|
||||||
if (!match(p, TOKEN_PIPE)) {
|
if (!match(p, TOKEN_PIPE)) {
|
||||||
error(p, "Expected `|` to close captures\n");
|
error(p, "expected capture.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
parseBody:;
|
|
||||||
|
arena_start = arena_snapshot(p->allocator);
|
||||||
|
node->expr.fr.captures = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->expr.fr.captures->type = NODE_UNIT;
|
||||||
|
node->expr.fr.captures->expr.unit_node.expr = parse_expression(p);
|
||||||
|
if (node->expr.fr.captures->expr.unit_node.expr && node->expr.fr.captures->expr.unit_node.expr->type != NODE_IDENTIFIER) {
|
||||||
|
error(p, "captures must be identifiers.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tail = node->expr.fr.captures;
|
||||||
|
node->expr.fr.capture_len = 1;
|
||||||
|
|
||||||
|
/* In this case, there is only one capture */
|
||||||
|
if (match(p, TOKEN_PIPE)) {
|
||||||
|
goto parse_body;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match(p, TOKEN_COMMA)) {
|
||||||
|
ast_node *expr = parse_expression(p);
|
||||||
|
if (expr) {
|
||||||
|
while (!match(p, TOKEN_PIPE)) {
|
||||||
|
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.fr.capture_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 identifier.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error(p, "expected `|`.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_body:;
|
||||||
|
if (node->expr.fr.capture_len != node->expr.fr.slice_len) {
|
||||||
|
error(p, "invalid number of captures.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ast_node* body = parse_compound(p);
|
ast_node* body = parse_compound(p);
|
||||||
node->expr.fr.body = body;
|
node->expr.fr.body = body;
|
||||||
return node;
|
return node;
|
||||||
|
|
|
||||||
11
parser.h
11
parser.h
|
|
@ -156,12 +156,11 @@ typedef struct _ast_node {
|
||||||
struct _ast_node *path;
|
struct _ast_node *path;
|
||||||
} import;
|
} import;
|
||||||
struct {
|
struct {
|
||||||
struct _ast_node *range;
|
/* These should be lists of unit_node */
|
||||||
struct _ast_node *array;
|
struct _ast_node *slices;
|
||||||
const char* rangeCapture;
|
struct _ast_node *captures;
|
||||||
const char* arrayCapture;
|
int capture_len;
|
||||||
int rangeCaptureLen;
|
int slice_len;
|
||||||
int arrayCaptureLen;
|
|
||||||
struct _ast_node* body;
|
struct _ast_node* body;
|
||||||
} fr; // for
|
} fr; // for
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
16
test.c
16
test.c
|
|
@ -1,17 +1,3 @@
|
||||||
//import example.test.idk.idk;
|
loop (0..1, list, 4..5, test, idk) |i, v, k, e, s| {
|
||||||
|
|
||||||
//hello:
|
|
||||||
//goto test;
|
|
||||||
//return 5;
|
|
||||||
|
|
||||||
// loop(0..15) |i| {
|
|
||||||
// printf("%d\n", i);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return 6;
|
|
||||||
|
|
||||||
loop (0.., list) |i, v| {
|
|
||||||
printf("%d\n", i);
|
printf("%d\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 7;
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue