summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Maniero <carlosmaniero@gmail.com>2023-04-20 13:42:10 -0300
committerJohnny Richard <johnny@johnnyrichard.com>2023-04-20 18:57:43 +0200
commit219dfdfdc98529ce173f894b79d88919a65c2808 (patch)
tree8792c686d05b107875d43f570ed6666f91dda19e /src
parent58da5195ef7d517f851ebfabfe79cfa27c0b2dde (diff)
parser: Create the literal node type
Since we want to extend our code to support multiple kind of expression it does not make sense that the return statement always return a number. For now on, return statement has an ast_node_t as argument, meaning that it could be anything. The literal_node_t was also implemented in order to keep the application behavior. Following the C's calling convention the literal values are stored at %eax and the return takes this argument to do anything it is needed. Signed-off-by: Carlos Maniero <carlosmaniero@gmail.com> Reviewed-by: Johnny Richard <johnny@johnnyrichard.com>
Diffstat (limited to 'src')
-rw-r--r--src/ast.c26
-rw-r--r--src/ast.h25
-rw-r--r--src/gas_assembly_generator.c19
-rw-r--r--src/parser.c43
4 files changed, 99 insertions, 14 deletions
diff --git a/src/ast.c b/src/ast.c
index 50f6a2e..7f3af9e 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -39,6 +39,12 @@ ast_node_return_stmt_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
visitor->visit_return_stmt(visitor, &node->data.return_stmt);
}
+static void
+ast_node_literal_visitor(ast_node_t *node, ast_visitor_t *visitor)
+{
+ visitor->visit_literal(visitor, &node->data.literal);
+}
+
ast_node_t*
ast_node_new()
{
@@ -62,6 +68,8 @@ ast_node_destroy(ast_node_t *node)
break;
case AST_UNKOWN_NODE:
break;
+ case AST_LITERAL:
+ break;
default:
assert(false && "unmapped free strategy");
}
@@ -69,13 +77,13 @@ ast_node_destroy(ast_node_t *node)
}
void
-ast_node_init_return_stmt(ast_node_t *node, uint32_t number)
+ast_node_init_return_stmt(ast_node_t *node, ast_node_t *argument)
{
node->accept_visitor = &ast_node_return_stmt_accept_visitor,
node->kind = AST_RETURN_STMT;
node->data = (ast_node_data_t) {
.return_stmt = {
- .number = number
+ .argument = argument
}
};
}
@@ -94,3 +102,17 @@ ast_node_init_function_declaration(ast_node_t *node, string_view_t name, type_t
};
}
+void
+ast_literal_integer_create(ast_node_t *node, uint32_t number)
+{
+ node->accept_visitor = &ast_node_literal_visitor;
+ node->kind = AST_LITERAL;
+ node->data = (ast_node_data_t) {
+ .literal = {
+ .kind = AST_LITERAL_INTEGER,
+ .value = {
+ .integer = number
+ }
+ }
+ };
+}
diff --git a/src/ast.h b/src/ast.h
index fab90c1..1c4bbb8 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -29,7 +29,7 @@ typedef struct ast_visitor_t ast_visitor_t;
typedef struct ast_node_t ast_node_t;
typedef struct ast_return_stmt_t {
- uint32_t number;
+ ast_node_t* argument;
} ast_return_stmt_t;
typedef struct ast_function_declaration_t {
@@ -38,19 +38,35 @@ typedef struct ast_function_declaration_t {
ast_node_t* body;
} ast_function_declaration_t;
+typedef enum {
+ AST_LITERAL_INTEGER
+} ast_literal_kind_t;
+
+typedef union {
+ uint32_t integer;
+} ast_literal_value_t;
+
+typedef struct ast_literal_t {
+ ast_literal_kind_t kind;
+ ast_literal_value_t value;
+} ast_literal_t;
+
typedef struct ast_visitor_t {
void (*visit_function)(struct ast_visitor_t *, ast_function_declaration_t *);
void (*visit_return_stmt)(struct ast_visitor_t *, ast_return_stmt_t *);
+ void (*visit_literal)(struct ast_visitor_t *, ast_literal_t *);
} ast_visitor_t;
typedef enum {
- AST_UNKOWN_NODE,
AST_FUNCTION_DECLARATION,
- AST_RETURN_STMT
+ AST_LITERAL,
+ AST_RETURN_STMT,
+ AST_UNKOWN_NODE
} ast_node_kind_t;
typedef union {
ast_function_declaration_t function;
+ ast_literal_t literal;
ast_return_stmt_t return_stmt;
} ast_node_data_t;
@@ -66,7 +82,8 @@ ast_node_t* ast_node_new();
void ast_node_destroy(ast_node_t *node);
void ast_node_init_function_declaration(ast_node_t* node, string_view_t name, type_t return_type, ast_node_t *body);
-void ast_node_init_return_stmt(ast_node_t* node, uint32_t number);
+void ast_node_init_return_stmt(ast_node_t* node, ast_node_t *argument);
+void ast_literal_integer_create(ast_node_t* node, uint32_t number);
#endif /* AST_H */
diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c
index afbfebd..755b0be 100644
--- a/src/gas_assembly_generator.c
+++ b/src/gas_assembly_generator.c
@@ -22,6 +22,7 @@
static void gas_assembly_generator_visit_function(ast_visitor_t *visitor, ast_function_declaration_t *func);
static void gas_assembly_generator_visit_return_stmt(ast_visitor_t *visitor, ast_return_stmt_t *return_stmt);
+static void gas_assembly_generator_visit_literal(ast_visitor_t *visitor, ast_literal_t *return_stmt);
void
gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *out)
@@ -29,6 +30,7 @@ gas_assembly_generator_init(gas_assembly_generator_t *gen, FILE *out)
assert(gen && out);
gen->super = (ast_visitor_t) {
.visit_function = &gas_assembly_generator_visit_function,
+ .visit_literal = &gas_assembly_generator_visit_literal,
.visit_return_stmt = &gas_assembly_generator_visit_return_stmt
};
gen->out = out;
@@ -59,8 +61,23 @@ gas_assembly_generator_visit_return_stmt(ast_visitor_t *visitor, ast_return_stmt
assert(visitor && return_stmt);
gas_assembly_generator_t *gen = (gas_assembly_generator_t *) visitor;
+ ast_visitor_visit(visitor, return_stmt->argument);
+
+ fprintf(gen->out, " mov %%eax, %%ebx\n");
+ fprintf(gen->out, " mov $1, %%al\n");
fprintf(gen->out, " mov $1, %%al\n");
- fprintf(gen->out, " mov $%d, %%ebx\n", return_stmt->number);
fprintf(gen->out, " int $0x80\n");
}
+static void
+gas_assembly_generator_visit_literal(ast_visitor_t *visitor, ast_literal_t *literal)
+{
+ gas_assembly_generator_t *gen = (gas_assembly_generator_t *) visitor;
+ switch (literal->kind) {
+ case AST_LITERAL_INTEGER:
+ fprintf(gen->out, " mov $%d, %%eax\n", literal->value.integer);
+ return;
+ default:
+ assert(false && "No code generation strategy.");
+ }
+}
diff --git a/src/parser.c b/src/parser.c
index 4646de0..176a4a8 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -99,6 +99,39 @@ parser_parse_type(type_t *type, parser_t *parser)
}
bool
+parser_literal_integer_node(ast_node_t *node, token_t *token)
+{
+ char number_as_str[token->value.size];
+ string_view_to_str(&token->value, number_as_str);
+
+ ast_literal_integer_create(node, atoi(number_as_str));
+ return true;
+}
+
+bool
+parser_parse_next_expression(parser_t *parser, ast_node_t *node)
+{
+ token_t token;
+ lexer_next_token(parser->lexer, &token);
+
+ if (token.kind == TOKEN_NUMBER)
+ {
+ return parser_literal_integer_node(node, &token);
+ }
+
+ parser_error_t error;
+ error.token = token;
+ sprintf(
+ error.message,
+ "unexpected '%s ("SVFMT")' token",
+ token_kind_to_str(token.kind),
+ SVARG(&token.value)
+ );
+ parser->errors[parser->errors_len++] = error;
+ return false;
+}
+
+bool
parser_parse_return_stmt(parser_t *parser, ast_node_t *node)
{
token_t return_keyword_token;
@@ -121,17 +154,13 @@ parser_parse_return_stmt(parser_t *parser, ast_node_t *node)
return false;
}
- token_t number_token;
-
- if (!expected_token(&number_token, parser, TOKEN_NUMBER)) return false;
+ ast_node_t *argument_token = ast_node_new();
+ if (!parser_parse_next_expression(parser, argument_token)) return false;
if (!drop_expected_token(parser, TOKEN_SEMICOLON)) return false;
if (!drop_expected_token(parser, TOKEN_CCURLY)) return false;
- char number_as_str[number_token.value.size];
- string_view_to_str(&number_token.value, number_as_str);
-
- ast_node_init_return_stmt(node, atoi(number_as_str));
+ ast_node_init_return_stmt(node, argument_token);
return true;
}