summaryrefslogtreecommitdiff
path: root/src/frontend/driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/driver.c')
-rw-r--r--src/frontend/driver.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/frontend/driver.c b/src/frontend/driver.c
new file mode 100644
index 0000000..52eb3f4
--- /dev/null
+++ b/src/frontend/driver.c
@@ -0,0 +1,88 @@
+#include "lexer.h"
+#include "parser.h"
+#include "node.h"
+#include <stdio.h>
+#include <libguile.h>
+
+/**
+ * @param node a tree of node structs representing a C source file.
+ * @return a scheme representation of node.
+ */
+SCM
+node_to_scm(Node *node) {
+ SCM ret = scm_list_1(scm_from_locale_symbol(node_types[node->type]));
+
+ SCM field_value = SCM_BOOL_F;
+ switch (node->type) {
+ case FUNC:
+ field_value = scm_from_locale_string(node->field.name);
+ break;
+ case EXPR:
+ field_value = scm_from_locale_symbol(node_ops[node->field.op]);
+ break;
+ case CONST:
+ field_value = scm_from_int32(node->field.val);
+ break;
+ default:
+ ;
+ }
+
+ if (scm_is_true(field_value))
+ ret = scm_append(scm_list_2(ret, scm_list_1(field_value)));
+
+ SCM child;
+ for (size_t i = 0; i < node->num_children; ++i) {
+ child = node_to_scm(node->children[i]);
+ ret = scm_append(scm_list_2(ret, scm_list_1(child)));
+ }
+
+ return ret;
+}
+
+/** \brief Parser driver for ull.
+ * Given F, returns an AST of the program represented as a guile s-exp, or #f on a parse error.
+ * if DO_PARSE is false, only performs lexing, returning #t on a success.
+ * @param f a preprocessed C file to parse.
+ * @param do_parse on false, do not perform the parsing stage.
+ * @return a SCM list representing the parse tree, or #t if do_parse is #f and lexing is successful, or #f otherwise.
+ */
+SCM
+file_to_ast_wrapper(SCM f, SCM do_parse)
+{
+ char *file = scm_to_locale_string(f);
+ Node *root = NULL;
+ SCM ret = SCM_BOOL_F;
+
+ yyin = fopen(file, "r");
+ if (yyin != NULL){
+ if (scm_is_true(do_parse)) {
+ if (yyparse(&root) == 0) {
+ ret = node_to_scm(root);
+ free_node(root);
+ }
+ } else {
+ ret = SCM_BOOL_T;
+ int token;
+ while ((token = yylex()) != 0) {
+ if (token == YYerror)
+ ret = SCM_BOOL_F;
+ }
+ }
+ }
+
+ fclose(yyin);
+ free(file);
+ return ret;
+}
+
+void
+init_parser_driver()
+{
+ scm_c_define_gsubr("file->ast", 2, 0, 0, file_to_ast_wrapper);
+ scm_c_export("file->ast", NULL);
+}
+
+void
+scm_init_parser_driver_module() {
+ scm_c_define_module("frontend driver", init_parser_driver, NULL);
+}