summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..59a41a2
--- /dev/null
+++ b/main.c
@@ -0,0 +1,161 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lex.h"
+
+/* node graph */
+
+typedef enum {
+ N_START,
+ N_STOP,
+ N_LIT_INT,
+ N_OP_ADD,
+ N_OP_SUB,
+ N_OP_MUL,
+ N_OP_DIV,
+ N_OP_NEG,
+} NodeType;
+
+typedef struct Node {
+ NodeType type;
+ struct Node **inputs, **outputs;
+} Node;
+
+typedef struct {
+ Node *start, *stop;
+} ProcGraph;
+
+/* parsing */
+
+void parse_expr(Lexer *l);
+
+void parse_stmt_let(Lexer *l) {
+ lex_expect(l, TMASK(TOK_IDENT));
+ Str name = l->ident;
+ lex_expect(l, TMASK(TOK_EQUALS) | TMASK(TOK_COLON));
+ lex_next(l);
+ parse_expr(l);
+ printf("name_bind %.*s\n", (int)name.n, name.s);
+}
+
+void parse_stmt(Lexer *l) {
+ /* TODO */
+ (void)l;
+ switch (l->tok) {
+ case TOK_LET:
+ parse_stmt_let(l);
+ break;
+ case TOK_RETURN:
+ lex_next(l);
+ parse_expr(l);
+ puts("return");
+ break;
+ default:
+ lex_expected(l, TMASK(TOK_RBRACE));
+ }
+}
+
+void parse_proc(Lexer *l) {
+ lex_expect(l, TMASK(TOK_IDENT));
+ lex_expect(l, TMASK(TOK_LBRACE));
+ lex_next(l);
+ while (l->tok != TOK_RBRACE) {
+ lex_expected_not(l, TMASK(TOK_EOF));
+ parse_stmt(l);
+ }
+ lex_expected(l, TMASK(TOK_RBRACE));
+ lex_next(l);
+}
+
+void parse_term(Lexer *l) {
+ int negate_after = l->tok == TOK_MINUS;
+ if (TMASK(l->tok) & (TMASK(TOK_MINUS) | TMASK(TOK_PLUS))) {
+ lex_next(l);
+ }
+ if (l->tok == TOK_LPAREN) {
+ lex_next(l);
+ parse_expr(l);
+ lex_expected(l, TMASK(TOK_RPAREN));
+ lex_next(l);
+ } else {
+ lex_expected(l, TMASK(TOK_LIT_NUM) | TMASK(TOK_LIT_STR) | TMASK(TOK_LIT_CHAR) | TMASK(TOK_IDENT));
+ switch (l->tok) {
+ case TOK_IDENT:
+ printf("var %.*s\n", (int)l->ident.n, l->ident.s);
+ break;
+ case TOK_LIT_STR:
+ printf("lit_str %.*s\n", (int)l->ident.n, l->ident.s);
+ break;
+ case TOK_LIT_CHAR:
+ printf("lit_char %.*s\n", (int)l->ident.n, l->ident.s);
+ break;
+ case TOK_LIT_NUM:
+ printf("lit_num %.*s\n", (int)l->ident.n, l->ident.s);
+ break;
+ default:
+ break;
+ }
+ lex_next(l);
+ }
+ if (negate_after) puts("negate");
+}
+
+void parse_expr(Lexer *l) {
+ parse_term(l);
+ if (l->tok == TOK_LPAREN) {
+ lex_next(l);
+ puts("args_start");
+ for (;;) {
+ parse_expr(l);
+ lex_expected(l, TMASK(TOK_COMMA) | TMASK(TOK_RPAREN));
+ if (l->tok == TOK_RPAREN) break;
+ lex_next(l);
+ }
+ lex_next(l);
+ puts("args_end");
+ puts("func_call");
+ }
+ if (TMASK(l->tok) & (TMASK(TOK_PLUS) | TMASK(TOK_MINUS) | TMASK(TOK_ASTERISK) | TMASK(TOK_SLASH))) {
+ Token t = l->tok;
+ lex_next(l);
+ parse_expr(l);
+ switch (t) {
+ case TOK_PLUS: puts("add"); break;
+ case TOK_MINUS: puts("subtract"); break;
+ case TOK_ASTERISK: puts("multiply"); break;
+ case TOK_SLASH: puts("divide"); break;
+ default: break;
+ }
+ }
+}
+
+void parse_decl(Lexer *l) {
+ switch (l->tok) {
+ case TOK_PROC:
+ parse_proc(l);
+ break;
+ default:
+ lex_error(l, LE_ERROR, S("Invalid declaration statement"));
+ }
+}
+
+void parse_unit(Lexer *l) {
+ while (l->tok != TOK_EOF) {
+ parse_decl(l);
+ }
+}
+
+int main(int argc, const char **argv) {
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s FILE\n", argv[0]);
+ return 1;
+ }
+ Lexer l = { 0 };
+ lex_start(&l, argv[1]);
+ parse_unit(&l);
+ lex_free(&l);
+ return 0;
+}