summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast.c63
-rw-r--r--src/ast.h57
-rw-r--r--src/gas_assembly_generator.c66
-rw-r--r--src/gas_assembly_generator.h33
-rw-r--r--src/parser.c15
-rw-r--r--src/parser.h15
-rw-r--r--src/pipac.c14
7 files changed, 231 insertions, 32 deletions
diff --git a/src/ast.c b/src/ast.c
new file mode 100644
index 0000000..f8c2713
--- /dev/null
+++ b/src/ast.c
@@ -0,0 +1,63 @@
+/*
+* Copyright (C) 2023 Johnny Richard
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "ast.h"
+
+void
+ast_node_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
+{
+ assert(node);
+ assert(node->accept_visitor);
+ node->accept_visitor(node, visitor);
+}
+
+static void
+ast_function_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
+{
+ visitor->visit_function(visitor, (ast_function_t *) node);
+}
+
+static void
+ast_return_stmt_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
+{
+ visitor->visit_return_stmt(visitor, (ast_return_stmt_t *) node);
+}
+
+ast_return_stmt_t
+ast_return_stmt_create(uint32_t number)
+{
+ return (ast_return_stmt_t) {
+ .super = (ast_node_t) {
+ .accept_visitor = &ast_return_stmt_accept_visitor
+ },
+ .number = number
+ };
+}
+
+ast_function_t
+ast_function_create(string_view_t name, type_t return_type, ast_return_stmt_t body)
+{
+ return (ast_function_t) {
+ .super = (ast_node_t) {
+ .accept_visitor = &ast_function_accept_visitor
+ },
+ .name = name,
+ .return_type = return_type,
+ .body = body
+ };
+}
+
diff --git a/src/ast.h b/src/ast.h
new file mode 100644
index 0000000..7f5a198
--- /dev/null
+++ b/src/ast.h
@@ -0,0 +1,57 @@
+/*
+* Copyright (C) 2023 Johnny Richard
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef AST_H
+#define AST_H
+#include <stdint.h>
+#include "string_view.h"
+
+#define ast_visitor_visit(visitor, node) ast_node_accept_visitor((ast_node_t *) node, (ast_visitor_t *) visitor);
+
+typedef enum {
+ TYPE_I32
+} type_t;
+
+typedef struct ast_visitor_t ast_visitor_t;
+
+typedef struct ast_node_t {
+ void (*accept_visitor)(struct ast_node_t *, ast_visitor_t *);
+} ast_node_t;
+
+typedef struct ast_return_stmt_t {
+ struct ast_node_t super;
+ uint32_t number;
+} ast_return_stmt_t;
+
+typedef struct ast_function_t {
+ struct ast_node_t super;
+ string_view_t name;
+ type_t return_type;
+ ast_return_stmt_t body;
+} ast_function_t;
+
+typedef struct ast_visitor_t {
+ void (*visit_function)(struct ast_visitor_t *, ast_function_t *);
+ void (*visit_return_stmt)(struct ast_visitor_t *, ast_return_stmt_t *);
+} ast_visitor_t;
+
+void ast_node_accept_visitor(ast_node_t *node, ast_visitor_t *visitor);
+
+ast_function_t ast_function_create(string_view_t name, type_t return_type, ast_return_stmt_t body);
+ast_return_stmt_t ast_return_stmt_create(uint32_t number);
+
+#endif /* AST_H */
+
diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c
new file mode 100644
index 0000000..d164b7d
--- /dev/null
+++ b/src/gas_assembly_generator.c
@@ -0,0 +1,66 @@
+/*
+* Copyright (C) 2023 Johnny Richard
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#include "gas_assembly_generator.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void gas_assembly_generator_visit_function(ast_visitor_t *visitor, ast_function_t *func);
+static void gas_assembly_generator_visit_return_stmt(ast_visitor_t *visitor, ast_return_stmt_t *return_stmt);
+
+void
+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_return_stmt = &gas_assembly_generator_visit_return_stmt
+ };
+ gen->out = out;
+}
+
+static void
+gas_assembly_generator_visit_function(ast_visitor_t *visitor, ast_function_t *func)
+{
+ assert(visitor && func);
+
+ if (!string_view_eq(func->name, string_view_from_str("main"))) {
+ fprintf(stderr, "[ERROR]: no main function has been defined!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ gas_assembly_generator_t *gen = (gas_assembly_generator_t *) visitor;
+
+ fprintf(gen->out,".global _start\n");
+ fprintf(gen->out,".text\n");
+ fprintf(gen->out,"_start:\n");
+
+ ast_visitor_visit(visitor, &func->body);
+}
+
+static void
+gas_assembly_generator_visit_return_stmt(ast_visitor_t *visitor, ast_return_stmt_t *return_stmt)
+{
+ assert(visitor && return_stmt);
+ gas_assembly_generator_t *gen = (gas_assembly_generator_t *) visitor;
+
+ fprintf(gen->out, " mov $1, %%al\n");
+ fprintf(gen->out, " mov $%d, %%ebx\n", return_stmt->number);
+ fprintf(gen->out, " int $0x80\n");
+}
+
diff --git a/src/gas_assembly_generator.h b/src/gas_assembly_generator.h
new file mode 100644
index 0000000..64f861e
--- /dev/null
+++ b/src/gas_assembly_generator.h
@@ -0,0 +1,33 @@
+/*
+* Copyright (C) 2023 Johnny Richard
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef GAS_ASSEMBLY_GENERATOR_H
+#define GAS_ASSEMBLY_GENERATOR_H
+
+#include "ast.h"
+#include <stdio.h>
+
+typedef struct gas_assembly_generator_t {
+ ast_visitor_t super;
+ FILE *out;
+} gas_assembly_generator_t;
+
+void gas_assembly_generator_init(gas_assembly_generator_t *, FILE *);
+
+void gas_assembly_generator_visit(gas_assembly_generator_t * gen, ast_node_t* ast);
+
+#endif /* GAS_ASSEMBLY_GENERATOR_H */
+
diff --git a/src/parser.c b/src/parser.c
index 593f75a..b956c4e 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
+#include "ast.h"
#include "lexer.h"
#include "parser.h"
@@ -92,9 +93,7 @@ parser_parse_return_stmt(parser_t *parser)
char number_as_str[number_token.value.size];
string_view_to_str(&number_token.value, number_as_str);
- return (ast_return_stmt_t) {
- .number = atoi(number_as_str)
- };
+ return ast_return_stmt_create(atoi(number_as_str));
}
ast_function_t
@@ -106,9 +105,9 @@ parser_parse_function(parser_t *parser)
expected_token(parser, TOKEN_COLON);
type_t return_type = parser_parse_type(parser);
- return (ast_function_t) {
- .name = func_name_token.value,
- .return_type = return_type,
- .body = parser_parse_return_stmt(parser)
- };
+ return ast_function_create(
+ func_name_token.value,
+ return_type,
+ parser_parse_return_stmt(parser)
+ );
}
diff --git a/src/parser.h b/src/parser.h
index d44a4df..b846ae1 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -17,6 +17,7 @@
#ifndef PARSER_H
#define PARSER_H
+#include "ast.h"
#include "lexer.h"
#include "string_view.h"
@@ -24,20 +25,6 @@ typedef struct parser_t {
lexer_t *lexer;
} parser_t;
-typedef enum {
- TYPE_I32
-} type_t;
-
-typedef struct ast_return_stmt_t {
- uint32_t number;
-} ast_return_stmt_t;
-
-typedef struct ast_function_t {
- string_view_t name;
- type_t return_type;
- ast_return_stmt_t body;
-} ast_function_t;
-
void parser_init(parser_t *parser, lexer_t *lexer);
ast_function_t parser_parse_function(parser_t *parser);
diff --git a/src/pipac.c b/src/pipac.c
index 6e6df9e..e56d8a1 100644
--- a/src/pipac.c
+++ b/src/pipac.c
@@ -21,21 +21,15 @@
#include "lexer.h"
#include "parser.h"
#include "string_view.h"
+#include "gas_assembly_generator.h"
void
generate_gas_x86_64_linux(ast_function_t *func)
{
- if (!string_view_eq(func->name, string_view_from_str("main"))) {
- fprintf(stderr, "[ERROR]: no main function has been defined!\n");
- exit(EXIT_FAILURE);
- }
+ gas_assembly_generator_t gen;
+ gas_assembly_generator_init(&gen, stdout);
- printf(".global _start\n");
- printf(".text\n");
- printf("_start:\n");
- printf(" mov $1, %%al\n");
- printf(" mov $%d, %%ebx\n", func->body.number);
- printf(" int $0x80\n");
+ ast_visitor_visit(&gen, func);
}
void