aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-01-28 18:45:18 -0500
committerMustafa Quraish <[email protected]>2022-01-28 22:38:02 -0500
commit0874e5e5440c802415291c8f3d5ec040167445eb (patch)
treea3a27e521ba1e896e517d47ba98fca1d69fa980f
parentAdd some scripts to help assemble generated output and run it (diff)
downloadcup-0874e5e5440c802415291c8f3d5ec040167445eb.tar.xz
cup-0874e5e5440c802415291c8f3d5ec040167445eb.zip
Lexer+Parser: Add support for some unary operations
-rw-r--r--cup/ast.c9
-rw-r--r--cup/ast.h3
-rw-r--r--cup/lexer.c4
-rw-r--r--cup/main.c8
-rw-r--r--cup/parser.c29
-rw-r--r--cup/tokens.h5
6 files changed, 50 insertions, 8 deletions
diff --git a/cup/ast.c b/cup/ast.c
index 2f3d94d..6adf0d0 100644
--- a/cup/ast.c
+++ b/cup/ast.c
@@ -59,6 +59,15 @@ static void do_print_ast(Node *node, int depth)
} else if (node->type == AST_RETURN) {
printf("return\n");
do_print_ast(node->unary_expr, depth + 1);
+ } else if (node->type == OP_NEG) {
+ printf("-\n");
+ do_print_ast(node->unary_expr, depth + 1);
+ } else if (node->type == OP_NOT) {
+ printf("!\n");
+ do_print_ast(node->unary_expr, depth + 1);
+ } else if (node->type == OP_BWINV) {
+ printf("~\n");
+ do_print_ast(node->unary_expr, depth + 1);
} else {
printf("(unknown)\n");
}
diff --git a/cup/ast.h b/cup/ast.h
index 6170489..c35ab87 100644
--- a/cup/ast.h
+++ b/cup/ast.h
@@ -3,6 +3,9 @@
#include <stdbool.h>
#define ENUM_AST_TYPES(F) \
+ F(OP_NEG, "neg") \
+ F(OP_NOT, "!") \
+ F(OP_BWINV, "~") \
F(OP_PLUS, "+") \
F(OP_MINUS, "-") \
F(OP_MUL, "*") \
diff --git a/cup/lexer.c b/cup/lexer.c
index 9f9af90..d03ea78 100644
--- a/cup/lexer.c
+++ b/cup/lexer.c
@@ -93,6 +93,8 @@ Token Lexer_next(Lexer *lexer)
case ';': return Lexer_make_token(lexer, TOKEN_SEMICOLON, 1);
case ':': return Lexer_make_token(lexer, TOKEN_COLON, 1);
case '&': return Lexer_make_token(lexer, TOKEN_AMPERSAND, 1);
+ case '~': return Lexer_make_token(lexer, TOKEN_TILDE, 1);
+ case '!': return Lexer_make_token(lexer, TOKEN_EXCLAMATION, 1);
case '<': {
if (peek(lexer, 1) == '=')
@@ -176,7 +178,7 @@ Token Lexer_next(Lexer *lexer)
}
- printf("Shouldn't have gotten here... char is '%c'\n", lexer->src[lexer->pos]);
+ die_location(Lexer_loc(lexer), ": ERROR: Unexpected character '%c'\n", lexer->src[lexer->pos]);
advance(lexer, 1);
}
}
diff --git a/cup/main.c b/cup/main.c
index 1212d33..a5bce4b 100644
--- a/cup/main.c
+++ b/cup/main.c
@@ -3,6 +3,7 @@
#include <string.h>
#include "lexer.h"
#include "parser.h"
+#include "generator.h"
#include "unistd.h"
int main(int argc, char**argv) {
@@ -21,7 +22,12 @@ int main(int argc, char**argv) {
// Lexer
Lexer lexer = Lexer_new(filename, source, fsize);
Node *ast = parse_program(&lexer);
- print_ast(ast);
+
+ print_ast(ast);
+
+ FILE *f = fopen("output.nasm", "w");
+ generate_asm(ast, f);
+
// Token token;
// while ( (token = Lexer_next(&lexer)).type != TOKEN_EOF) {
// Token_print(stdout, &token);
diff --git a/cup/parser.c b/cup/parser.c
index 0d0ce46..746a139 100644
--- a/cup/parser.c
+++ b/cup/parser.c
@@ -50,17 +50,38 @@ Type parse_type(Lexer *lexer)
return type;
}
-Node *parse_expression(Lexer *lexer)
+Node *parse_literal(Lexer *lexer)
{
- // TODO: Parse more complicated things
- Token token;
Node *node = Node_new(AST_LITERAL);
- token = assert_token(Lexer_next(lexer), TOKEN_INTLIT);
+ Token token = assert_token(Lexer_next(lexer), TOKEN_INTLIT);
node->literal.type = (Type) {.type = TYPE_INT};
node->literal.as_int = token.value.as_int;
return node;
}
+Node *parse_expression(Lexer *lexer)
+{
+ // TODO: Parse more complicated things
+ Token token = Lexer_peek(lexer);
+ Node *expr;
+ if (token.type == TOKEN_MINUS) {
+ Lexer_next(lexer);
+ expr = Node_new(OP_NEG);
+ expr->unary_expr = parse_expression(lexer);
+ } else if (token.type == TOKEN_TILDE) {
+ Lexer_next(lexer);
+ expr = Node_new(OP_BWINV);
+ expr->unary_expr = parse_expression(lexer);
+ } else if (token.type == TOKEN_EXCLAMATION) {
+ Lexer_next(lexer);
+ expr = Node_new(OP_NOT);
+ expr->unary_expr = parse_expression(lexer);
+ } else {
+ return parse_literal(lexer);
+ }
+ return expr;
+}
+
Node *parse_statement(Lexer *lexer)
{
Node *node;
diff --git a/cup/tokens.h b/cup/tokens.h
index 56ad40c..d8b5070 100644
--- a/cup/tokens.h
+++ b/cup/tokens.h
@@ -16,6 +16,7 @@ typedef int64_t i64;
F(TOKEN_COLON, ":") \
F(TOKEN_EOF, "EOF") \
F(TOKEN_EQ, "==") \
+ F(TOKEN_EXCLAMATION, "!") \
F(TOKEN_FN, "fn") \
F(TOKEN_GEQ, ">=") \
F(TOKEN_GT, ">") \
@@ -43,6 +44,7 @@ typedef int64_t i64;
F(TOKEN_SLASH, "/") \
F(TOKEN_STAR, "*") \
F(TOKEN_STRINGLIT, "string literal") \
+ F(TOKEN_TILDE, "~") \
F(TOKEN_XOR, "^")
typedef enum {
@@ -53,8 +55,7 @@ typedef enum {
typedef struct {
char *filename;
- int line;
- int col;
+ int line, col;
} Location;
void Location_print(FILE *f, Location loc);