aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/ast.c5
-rw-r--r--src/parser/ast.h10
-rw-r--r--src/parser/parser.c45
3 files changed, 60 insertions, 0 deletions
diff --git a/src/parser/ast.c b/src/parser/ast.c
index 9bdf4d1..1aa1d38 100644
--- a/src/parser/ast.c
+++ b/src/parser/ast.c
@@ -36,6 +36,11 @@ static void free_statement(struct Statement* statement)
free_statement(statement->branch.body);
free(statement->branch.body);
break;
+ case STATEMENT_CALL:
+ for (size_t i = 0; i < statement->call.arg_count; i += 1)
+ free_expr(statement->call.args[i]);
+ free(statement->call.args);
+ break;
default:
break;
}
diff --git a/src/parser/ast.h b/src/parser/ast.h
index e85e72f..3fa80da 100644
--- a/src/parser/ast.h
+++ b/src/parser/ast.h
@@ -66,6 +66,7 @@ enum StatementKind
STATEMENT_GOTO,
STATEMENT_SYSCALL,
STATEMENT_IF,
+ STATEMENT_CALL,
};
struct AssignStatement
@@ -94,6 +95,14 @@ struct IfStatement
struct Statement* body;
};
+struct CallStatement
+{
+ struct Token name;
+ struct Expr** args;
+ size_t arg_count;
+ size_t arg_capacity;
+};
+
struct Statement
{
enum StatementKind kind;
@@ -103,6 +112,7 @@ struct Statement
struct LabelStatement label;
struct GotoStatement jump;
struct IfStatement branch;
+ struct CallStatement call;
};
};
diff --git a/src/parser/parser.c b/src/parser/parser.c
index 2ae52f2..55203ca 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -216,6 +216,48 @@ static bool is_compare_op(enum TokenType type)
|| type == TOKEN_GREATER_EQUAL;
}
+static bool parse_call(struct Parser* parser, struct Token name, struct Statement* out)
+{
+ struct Expr** args = NULL;
+ size_t count = 0;
+ size_t capacity = 0;
+
+ if (!check(parser, TOKEN_RIGHT_PAREN))
+ {
+ do
+ {
+ struct Expr* arg = parse_expression(parser);
+ if (arg == NULL)
+ goto error;
+
+ if (count == capacity)
+ {
+ capacity = capacity < 4 ? 4 : capacity * 2;
+ args = realloc(args, capacity * sizeof(struct Expr*));
+ }
+ args[count] = arg;
+ count += 1;
+ }
+ while (match_token(parser, TOKEN_COMMA));
+ }
+
+ if (!consume(parser, TOKEN_RIGHT_PAREN, "expected ')' after arguments"))
+ goto error;
+
+ out->kind = STATEMENT_CALL;
+ out->call.name = name;
+ out->call.args = args;
+ out->call.arg_count = count;
+ out->call.arg_capacity = capacity;
+ return true;
+
+error:
+ for (size_t i = 0; i < count; i += 1)
+ free_expr(args[i]);
+ free(args);
+ return false;
+}
+
static bool parse_statement(struct Parser* parser, struct Statement* out);
static bool parse_if(struct Parser* parser, struct Statement* out)
@@ -284,6 +326,9 @@ static bool parse_statement(struct Parser* parser, struct Statement* out)
return false;
struct Token name = parser->previous;
+ if (!deref && match_token(parser, TOKEN_LEFT_PAREN))
+ return parse_call(parser, name, out);
+
if (!deref && match_token(parser, TOKEN_COLON))
{
out->kind = STATEMENT_LABEL;