aboutsummaryrefslogtreecommitdiff
path: root/cup/parser.c
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-01-29 00:20:09 -0500
committerMustafa Quraish <[email protected]>2022-01-29 00:42:58 -0500
commit08056428cec5d1e63e471590ac09d82dcbfcab93 (patch)
treee71c34fb2a47780a6e01d8fa0a2af4b3bd3e7130 /cup/parser.c
parentAdd some arithmetic binary operations into lex+parse+generation (diff)
downloadarchived-cup-08056428cec5d1e63e471590ac09d82dcbfcab93.tar.xz
archived-cup-08056428cec5d1e63e471590ac09d82dcbfcab93.zip
Add relational and logical operators + refactor binop parser
We now support OR and AND with short circuiting! (Yet to be tested since we don't yet have local variables to play with). The binop parser took a bit of an overhaul factoring out the common code so that it's easier to describe the operator precendence relationships without being overly repetitive.
Diffstat (limited to 'cup/parser.c')
-rw-r--r--cup/parser.c66
1 files changed, 31 insertions, 35 deletions
diff --git a/cup/parser.c b/cup/parser.c
index a6ea9b2..68bd22d 100644
--- a/cup/parser.c
+++ b/cup/parser.c
@@ -122,41 +122,37 @@ Node *parse_factor(Lexer *lexer)
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;
-}
+#define BINOP_PARSER(next_parser, predicate) \
+ Node *expr = next_parser(lexer); \
+ Token token = Lexer_peek(lexer); \
+ while (predicate(token.type)) { \
+ Lexer_next(lexer); \
+ Node *op = Node_new(binary_token_to_op(token.type)); \
+ Node *right = next_parser(lexer); \
+ op->binary.left = expr; \
+ op->binary.right = right; \
+ expr = op; \
+ token = Lexer_peek(lexer); \
+ } \
+ return expr;
+
+bool is_term_token(TokenType type) { return type == TOKEN_STAR || type == TOKEN_SLASH || type == TOKEN_PERCENT; }
+Node *parse_term(Lexer *lexer) { BINOP_PARSER(parse_factor, is_term_token); }
+
+bool is_additive_token(TokenType type) { return type == TOKEN_PLUS || type == TOKEN_MINUS; }
+Node *parse_additive(Lexer *lexer) { BINOP_PARSER(parse_term, is_additive_token); }
+
+bool is_relational_token(TokenType type) { return type == TOKEN_LT || type == TOKEN_LEQ || type == TOKEN_GT || type == TOKEN_GEQ; }
+Node *parse_relational(Lexer *lexer) { BINOP_PARSER(parse_additive, is_relational_token); }
+
+bool is_equality_token(TokenType type) { return type == TOKEN_EQ || type == TOKEN_NEQ; }
+Node *parse_equality(Lexer *lexer) { BINOP_PARSER(parse_relational, is_equality_token); }
+
+bool is_logical_and_token(TokenType type) { return type == TOKEN_AND; }
+Node *parse_logical_and(Lexer *lexer) { BINOP_PARSER(parse_equality, is_logical_and_token); }
+
+bool is_logical_or_token(TokenType type) { return type == TOKEN_OR; }
+Node *parse_expression(Lexer *lexer) { BINOP_PARSER(parse_logical_and, is_logical_or_token); }
Node *parse_statement(Lexer *lexer)
{