diff options
| author | Mustafa Quraish <[email protected]> | 2022-01-29 00:20:09 -0500 |
|---|---|---|
| committer | Mustafa Quraish <[email protected]> | 2022-01-29 00:42:58 -0500 |
| commit | 08056428cec5d1e63e471590ac09d82dcbfcab93 (patch) | |
| tree | e71c34fb2a47780a6e01d8fa0a2af4b3bd3e7130 /cup/parser.c | |
| parent | Add some arithmetic binary operations into lex+parse+generation (diff) | |
| download | archived-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.c | 66 |
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) { |