aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/parser.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/src/parser/parser.c b/src/parser/parser.c
index ebf07c7..97b8569 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -238,6 +238,7 @@ static struct Expr* parse_primary(struct Parser* parser)
{
if (match_token(parser, TOKEN_CARET))
{
+ bool is_signed = match_token(parser, TOKEN_SIGNED);
enum StoreSize size = parse_store_size(parser);
struct Expr* address = parse_primary(parser);
@@ -245,6 +246,12 @@ static struct Expr* parse_primary(struct Parser* parser)
return NULL;
struct Expr* deref = alloc_expr(EXPR_DEREF);
+ if (deref == NULL)
+ {
+ free_expr(address);
+ return NULL;
+ }
+ deref->deref.is_signed = is_signed;
deref->deref.size = size;
deref->deref.address = address;
return deref;
@@ -291,6 +298,30 @@ static struct Expr* parse_postfix(struct Parser* parser)
return expr;
}
+static struct Expr* parse_unary(struct Parser* parser)
+{
+ if (match_token(parser, TOKEN_MINUS))
+ {
+ struct Token op = parser->previous;
+
+ struct Expr* operand = parse_unary(parser);
+ if (operand == NULL)
+ return NULL;
+
+ struct Expr* expr = alloc_expr(EXPR_UNARY);
+ if (expr == NULL)
+ {
+ free_expr(operand);
+ return NULL;
+ }
+ expr->unary.op = op;
+ expr->unary.operand = operand;
+ return expr;
+ }
+
+ return parse_postfix(parser);
+}
+
static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)(struct Parser*),
enum TokenType a, enum TokenType b, enum TokenType c)
{
@@ -322,7 +353,7 @@ static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)(
static struct Expr* parse_multiplicative(struct Parser* parser)
{
- return parse_binary(parser, parse_postfix, TOKEN_STAR, TOKEN_SLASH, TOKEN_PERCENT);
+ return parse_binary(parser, parse_unary, TOKEN_STAR, TOKEN_SLASH, TOKEN_PERCENT);
}
static struct Expr* parse_expression(struct Parser* parser)