aboutsummaryrefslogtreecommitdiff
path: root/cup/parser.c
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-01-28 23:01:17 -0500
committerMustafa Quraish <[email protected]>2022-01-28 23:01:17 -0500
commitf38482a373a1bf3e20c53e5d08f9af9ec16cb1bc (patch)
treefc3929a34b3c45131574c1bbe80320faadd43060 /cup/parser.c
parentCorrent incorrect `break` in Lexer (diff)
downloadarchived-cup-f38482a373a1bf3e20c53e5d08f9af9ec16cb1bc.tar.xz
archived-cup-f38482a373a1bf3e20c53e5d08f9af9ec16cb1bc.zip
Add some arithmetic binary operations into lex+parse+generation
Diffstat (limited to 'cup/parser.c')
-rw-r--r--cup/parser.c90
1 files changed, 82 insertions, 8 deletions
diff --git a/cup/parser.c b/cup/parser.c
index 746a139..a6ea9b2 100644
--- a/cup/parser.c
+++ b/cup/parser.c
@@ -16,6 +16,37 @@ Token do_assert_token(Token token, TokenType type, char *filename, int line)
#define assert_token(token, type) do_assert_token(token, type, __FILE__, __LINE__)
+/******
+ * Some helpers
+ */
+
+NodeType binary_token_to_op(TokenType type)
+{
+ switch (type)
+ {
+ case TOKEN_PLUS: return OP_PLUS;
+ case TOKEN_MINUS: return OP_MINUS;
+ case TOKEN_STAR: return OP_MUL;
+ case TOKEN_SLASH: return OP_DIV;
+ case TOKEN_PERCENT: return OP_MOD;
+ case TOKEN_LSHIFT: return OP_LSHIFT;
+ case TOKEN_RSHIFT: return OP_RSHIFT;
+ case TOKEN_AND: return OP_AND;
+ case TOKEN_OR: return OP_OR;
+ case TOKEN_XOR: return OP_XOR;
+ case TOKEN_EQ: return OP_EQ;
+ case TOKEN_NEQ: return OP_NEQ;
+ case TOKEN_LT: return OP_LT;
+ case TOKEN_LEQ: return OP_LEQ;
+ case TOKEN_GT: return OP_GT;
+ case TOKEN_GEQ: return OP_GEQ;
+
+ default: assert(false && "binary_token_to_op called with invalid token type");
+ }
+}
+
+
+
void Node_add_child(Node *parent, Node *child)
{
// TODO, use a vector
@@ -59,7 +90,9 @@ Node *parse_literal(Lexer *lexer)
return node;
}
-Node *parse_expression(Lexer *lexer)
+Node *parse_expression(Lexer *);
+
+Node *parse_factor(Lexer *lexer)
{
// TODO: Parse more complicated things
Token token = Lexer_peek(lexer);
@@ -67,17 +100,60 @@ Node *parse_expression(Lexer *lexer)
if (token.type == TOKEN_MINUS) {
Lexer_next(lexer);
expr = Node_new(OP_NEG);
- expr->unary_expr = parse_expression(lexer);
+ expr->unary_expr = parse_factor(lexer);
} else if (token.type == TOKEN_TILDE) {
Lexer_next(lexer);
expr = Node_new(OP_BWINV);
- expr->unary_expr = parse_expression(lexer);
+ expr->unary_expr = parse_factor(lexer);
} else if (token.type == TOKEN_EXCLAMATION) {
Lexer_next(lexer);
expr = Node_new(OP_NOT);
- expr->unary_expr = parse_expression(lexer);
+ expr->unary_expr = parse_factor(lexer);
+ } else if (token.type == TOKEN_OPEN_PAREN) {
+ Lexer_next(lexer);
+ expr = parse_expression(lexer);
+ assert_token(Lexer_next(lexer), TOKEN_CLOSE_PAREN);
+ } else if (token.type == TOKEN_INTLIT) {
+ expr = parse_literal(lexer);
} else {
- return parse_literal(lexer);
+ die_location(token.loc, "Expected token found in parse_factor: `%s`", token_type_to_str(token.type));
+ exit(1);
+ }
+ return expr;
+}
+
+Node *parse_term(Lexer *lexer)
+{
+ Node *expr = parse_factor(lexer);
+ Token token = Lexer_peek(lexer);
+ while (token.type == TOKEN_STAR ||
+ token.type == TOKEN_SLASH ||
+ token.type == TOKEN_PERCENT) {
+ Lexer_next(lexer);
+ Node *op = Node_new(binary_token_to_op(token.type));
+ Node *right = parse_factor(lexer);
+ op->binary.left = expr;
+ op->binary.right = right;
+ expr = op;
+ token = Lexer_peek(lexer);
+ }
+ return expr;
+}
+
+
+Node *parse_expression(Lexer *lexer)
+{
+ Node *expr = parse_term(lexer);
+ Token token = Lexer_peek(lexer);
+ while (token.type == TOKEN_PLUS ||
+ token.type == TOKEN_MINUS) {
+ Lexer_next(lexer);
+ Node *op = Node_new(binary_token_to_op(token.type));
+ Node *right = parse_term(lexer);
+ op->binary.left = expr;
+ op->binary.right = right;
+ expr = op;
+ token = Lexer_peek(lexer);
}
return expr;
}
@@ -93,9 +169,7 @@ Node *parse_statement(Lexer *lexer)
node->unary_expr = parse_expression(lexer);
assert_token(Lexer_next(lexer), TOKEN_SEMICOLON);
} else {
- printf("Unexpected token in parse_statement: ");
- Token_print(stdout, &token);
- printf("\n");
+ die_location(token.loc, ": Unexpected token in parse_statement: %s\n", token_type_to_str(token.type));
exit(1);
}