libmya 0.1.0
Library to parse Mya language.
Loading...
Searching...
No Matches
parse_expression.c
Go to the documentation of this file.
1#include "ast.h"
2#include "module.h"
3#include "parser.h"
4#include "stack.h"
5#include "types/operators.h"
6
7static unsigned int
8_parse_operator(module_t* module, ast_node_t* parent, stack_t* stack, token_t* token);
9
10static unsigned int
11_parse_binary_operator(module_t* module, ast_node_t* parent, stack_t* stack, token_t* token);
12
13static unsigned int
14_parse_unary_operator(module_t* module, ast_node_t* parent, stack_t* stack, token_t* token);
15
16unsigned int
18{
20 ast_node_t node;
21 token_t* current_token;
22 ast_node_t* child;
23 unsigned int ntokens = 0;
24
26
27 for (;;) {
28 current_token = &token[ntokens];
29
30 switch (current_token->type) {
31 case TK_OPEN_PARENS:
32 child = stack_push(&stack, NT_EXPRESSION, current_token);
33 ntokens += parse_expression(module, child, token + 1);
34
35 if (token[ntokens].type != TK_CLOSE_PARENS) {
37 module,
38 child->token->line,
39 child->token->column,
40 child->token->lexeme.length,
41 "Open parentheses starting here has not a expected close parentheses matching it."
42 );
43
44 return ntokens;
45 }
46
47 ntokens++;
48 break;
49 case TK_IDENTIFIER:
50 case TK_NUMBER:
51 stack_push(&stack, NT_EXPRESSION, current_token);
52 ntokens++;
53 break;
54 case TK_OPERATOR:
55 ntokens += _parse_operator(module, parent, &stack, current_token);
56 break;
57 case TK_SEMICOLON:
58 ntokens++;
59 case TK_CLOSE_PARENS:
60 case TK_COMMA:
61 case TK_EOF:
62 goto finish_expression;
63 default:
65 module,
66 current_token->line,
67 current_token->column,
68 current_token->lexeme.length,
69 "Unexpected token inside an expression."
70 );
71
72 ntokens++;
73 goto finish_expression;
74 }
75 }
76
77
78finish_expression:
79 // We expect to only have one expression on stack at end. It's the root node of the expression.
80
81 if (stack_isempty(&stack)) {
82 module_add_error(module, token->line, token->column, token->lexeme.length, "Malformed expression starting here.");
83 return ntokens;
84 }
85
86 stack_pop(&stack, &node);
87
88 if (! stack_isempty(&stack)) {
89 stack_pop(&stack, &node);
90
92 module,
93 node.token->line,
94 node.token->column,
95 node.token->lexeme.length,
96 "Unexpected expression starting here."
97 );
98
99 return ntokens + 1;
100 }
101
102 ast_insert_children(parent, &node);
103
104 return ntokens + 1;
105}
106
107static unsigned int
108_parse_operator(module_t* module, ast_node_t* parent, stack_t* stack, token_t* token)
109{
110 switch (token->value) {
111 case OP_NOT:
112 return _parse_unary_operator(module, parent, stack, token);
113 case OP_MINUS:
114 if (stack_isempty(stack)) {
115 return _parse_unary_operator(module, parent, stack, token);
116 }
117 case OP_AND:
118 case OP_DIV:
119 case OP_MULT:
120 case OP_OR:
121 case OP_PLUS:
122 case OP_SHIFT_LEFT:
123 case OP_SHIFT_RIGHT:
124 case OP_XOR:
125 return _parse_binary_operator(module, parent, stack, token);
126 default:
128 module,
129 token->line,
130 token->column,
132 "Unrecognized operator here. It's really a valid expression operator?"
133 );
134
135 return 1;
136 }
137}
138
139static unsigned int
140_parse_binary_operator(module_t* module, ast_node_t* parent, stack_t* stack, token_t* token)
141{
142 ast_node_t value1;
143
144 if (stack_pop(stack, &value1) != ERR_OK) {
146 module,
147 token->line,
148 token->column,
150 "Binary operator expects a valid value before it, like in: `value OPERATOR value`."
151 );
152
153 return 1;
154 };
155
157 ast_insert_children(op, &value1);
158
159 return parse_expression(module, op, token + 1);
160}
161
162static unsigned int
163_parse_unary_operator(module_t* module, ast_node_t* parent, stack_t* stack, token_t* token)
164{
166
167 return parse_expression(module, op, token + 1);
168}
ast_node_t * ast_insert_children(ast_node_t *parent, ast_node_t *child)
Insert a exitent AST node as children of the given parent node.
Definition ast.c:51
@ ERR_OK
Definition err.h:15
void module_add_error(module_t *module, unsigned int line, unsigned int column, unsigned int length, const char *message)
Add error for the given module.
Definition module.c:92
@ OP_SHIFT_LEFT
Definition operators.h:12
@ OP_NOT
Definition operators.h:9
@ OP_SHIFT_RIGHT
Definition operators.h:13
@ OP_PLUS
Definition operators.h:11
@ OP_DIV
Definition operators.h:6
@ OP_XOR
Definition operators.h:14
@ OP_MULT
Definition operators.h:8
@ OP_AND
Definition operators.h:5
@ OP_MINUS
Definition operators.h:7
@ OP_OR
Definition operators.h:10
unsigned int parse_expression(module_t *module, ast_node_t *parent, token_t *token)
Parse a mathematical expression adding it as a children on parent AST node.
void stack_init(stack_t *stack)
Initializes the given stack.
Definition stack.c:11
ast_node_t * stack_push(stack_t *stack, node_type_t type, token_t *token)
Push a new value on the stack.
Definition stack.c:27
error_code_t stack_pop(stack_t *stack, ast_node_t *value)
Pop a value from the stack.
Definition stack.c:47
bool stack_isempty(stack_t *stack)
Check if the given stack is empty.
Definition stack.c:59
token_t * token
Definition ast.h:26
unsigned int length
The length of the string.
Definition dstring.h:13
Struct that represents a Mya module.
Definition module.h:34
A struct representing a dynamic stack.
Definition stack.h:12
Struct for a Mya token.
Definition token.h:32
long long int value
Integer value of the token on TK_NUMBER tokens.
Definition token.h:36
token_type_t type
Token type.
Definition token.h:33
dstring_t lexeme
Lexeme of the token.
Definition token.h:37
unsigned int line
Token line inside the module.
Definition token.h:34
unsigned int column
Column of the token position on the line.
Definition token.h:35
struct ast_node ast_node_t
@ NT_EXPRESSION
Definition ast.h:12
struct module module_t
Struct that represents a Mya module.
struct stack stack_t
A struct representing a dynamic stack.
struct token token_t
Struct for a Mya token.
@ TK_NUMBER
Definition token.h:19
@ TK_IDENTIFIER
Definition token.h:17
@ TK_OPEN_PARENS
Definition token.h:22
@ TK_COMMA
Definition token.h:14
@ TK_CLOSE_PARENS
Definition token.h:12
@ TK_OPERATOR
Definition token.h:23
@ TK_EOF
Definition token.h:15
@ TK_SEMICOLON
Definition token.h:24