aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/ast.c3
-rw-r--r--src/parser/ast.h26
-rw-r--r--src/parser/parser.c41
3 files changed, 48 insertions, 22 deletions
diff --git a/src/parser/ast.c b/src/parser/ast.c
index 96ee479..f9f857d 100644
--- a/src/parser/ast.c
+++ b/src/parser/ast.c
@@ -18,6 +18,9 @@ void free_expr(struct Expr* expr)
case EXPR_MEMBER:
free_expr(expr->member.object);
break;
+ case EXPR_DEREF:
+ free_expr(expr->deref.address);
+ break;
}
free(expr);
diff --git a/src/parser/ast.h b/src/parser/ast.h
index a98f43b..fc7af2b 100644
--- a/src/parser/ast.h
+++ b/src/parser/ast.h
@@ -24,11 +24,21 @@ struct Param
struct Token reg;
};
+enum StoreSize
+{
+ STORE_SIZE_NONE,
+ STORE_SIZE_BYTE,
+ STORE_SIZE_WORD,
+ STORE_SIZE_DWORD,
+ STORE_SIZE_QWORD,
+};
+
enum ExprKind
{
EXPR_PRIMARY,
EXPR_BINARY,
EXPR_MEMBER,
+ EXPR_DEREF,
};
struct PrimaryExpr
@@ -49,6 +59,12 @@ struct MemberExpr
struct Token member;
};
+struct DerefExpr
+{
+ enum StoreSize size;
+ struct Expr* address;
+};
+
struct Expr
{
enum ExprKind kind;
@@ -57,18 +73,10 @@ struct Expr
struct PrimaryExpr primary;
struct BinaryExpr binary;
struct MemberExpr member;
+ struct DerefExpr deref;
};
};
-enum StoreSize
-{
- STORE_SIZE_NONE,
- STORE_SIZE_BYTE,
- STORE_SIZE_WORD,
- STORE_SIZE_DWORD,
- STORE_SIZE_QWORD,
-};
-
enum StatementKind
{
STATEMENT_ASSIGN,
diff --git a/src/parser/parser.c b/src/parser/parser.c
index beb6b04..969ed86 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -133,8 +133,35 @@ static struct Expr* alloc_expr(enum ExprKind kind)
return expr;
}
+static enum StoreSize parse_store_size(struct Parser* parser)
+{
+ if (match_token(parser, TOKEN_BYTE))
+ return STORE_SIZE_BYTE;
+ if (match_token(parser, TOKEN_WORD))
+ return STORE_SIZE_WORD;
+ if (match_token(parser, TOKEN_DWORD))
+ return STORE_SIZE_DWORD;
+ if (match_token(parser, TOKEN_QWORD))
+ return STORE_SIZE_QWORD;
+ return STORE_SIZE_NONE;
+}
+
static struct Expr* parse_primary(struct Parser* parser)
{
+ if (match_token(parser, TOKEN_CARET))
+ {
+ enum StoreSize size = parse_store_size(parser);
+
+ struct Expr* address = parse_primary(parser);
+ if (address == NULL)
+ return NULL;
+
+ struct Expr* deref = alloc_expr(EXPR_DEREF);
+ deref->deref.size = size;
+ deref->deref.address = address;
+ return deref;
+ }
+
if (check(parser, TOKEN_IDENTIFIER) || check(parser, TOKEN_INTEGER) || check(parser, TOKEN_CHAR))
{
advance_parser(parser);
@@ -350,19 +377,7 @@ static bool parse_statement(struct Parser* parser, struct Statement* out)
}
bool deref = match_token(parser, TOKEN_CARET);
-
- enum StoreSize store_size = STORE_SIZE_NONE;
- if (deref)
- {
- if (match_token(parser, TOKEN_BYTE))
- store_size = STORE_SIZE_BYTE;
- else if (match_token(parser, TOKEN_WORD))
- store_size = STORE_SIZE_WORD;
- else if (match_token(parser, TOKEN_DWORD))
- store_size = STORE_SIZE_DWORD;
- else if (match_token(parser, TOKEN_QWORD))
- store_size = STORE_SIZE_QWORD;
- }
+ enum StoreSize store_size = deref ? parse_store_size(parser) : STORE_SIZE_NONE;
if (!consume(parser, TOKEN_IDENTIFIER, "expected a statement"))
return false;