Kestrel Interface
Loading...
Searching...
No Matches
kest_expr_parser.c
Go to the documentation of this file.
1#include "kest_int.h"
2
3#ifndef PRINTLINES_ALLOWED
4#define PRINTLINES_ALLOWED 1
5#endif
6
7static const char *FNAME = "kest_expr_parser.c";
8
10{
11 if (!token) return 0;
12
13 if (strcmp(token, "-" ) == 0) return KEST_EXPR_NEG;
14 if (strcmp(token, "abs" ) == 0) return KEST_EXPR_ABS;
15 if (strcmp(token, "sqr" ) == 0) return KEST_EXPR_SQR;
16 if (strcmp(token, "sqrt") == 0) return KEST_EXPR_SQRT;
17 if (strcmp(token, "exp" ) == 0) return KEST_EXPR_EXP;
18 if (strcmp(token, "sin" ) == 0) return KEST_EXPR_SIN;
19 if (strcmp(token, "cos" ) == 0) return KEST_EXPR_COS;
20 if (strcmp(token, "tan" ) == 0) return KEST_EXPR_TAN;
21 if (strcmp(token, "sinh") == 0) return KEST_EXPR_SINH;
22 if (strcmp(token, "cosh") == 0) return KEST_EXPR_COSH;
23 if (strcmp(token, "tanh") == 0) return KEST_EXPR_TANH;
24 if (strcmp(token, "asin") == 0) return KEST_EXPR_ASIN;
25 if (strcmp(token, "acos") == 0) return KEST_EXPR_ACOS;
26 if (strcmp(token, "atan") == 0) return KEST_EXPR_ATAN;
27
28 return 0;
29}
30
32{
33 if (!token) return 0;
34
35 if (strcmp(token, "+") == 0) return KEST_EXPR_ADD;
36 if (strcmp(token, "-") == 0) return KEST_EXPR_SUB;
37 if (strcmp(token, "*") == 0) return KEST_EXPR_MUL;
38 if (strcmp(token, "/") == 0) return KEST_EXPR_DIV;
39 if (strcmp(token, "^") == 0) return KEST_EXPR_POW;
40
41 return 0;
42}
43
45{
46 switch (infix_type)
47 {
48 case KEST_EXPR_ADD:
50 case KEST_EXPR_MUL:
53 }
54
55 return -1;
56}
57
58// 1 for left, 0 for right
60{
61 switch (infix_type)
62 {
63 case KEST_EXPR_ADD:
64 case KEST_EXPR_SUB:
65 case KEST_EXPR_MUL:
66 case KEST_EXPR_DIV: return 1;
67 }
68
69 return 0;
70}
71
73 kest_token_ll *tokens,
74 kest_token_ll **next_token,
75 kest_token_ll *tokens_end,
76 int min_binding_power,
77 int depth)
78{
79 if (!tokens || !tokens->data)
80 return NULL;
81
82 int line = tokens->line;
83
84 if (depth > KEST_EXPR_REC_MAX_DEPTH)
85 {
86 kest_parser_error_at(ps, tokens, "Expression too deep.");
87 return NULL;
88 }
89
90 kest_token_ll *current = tokens;
91 kest_token_ll *nt = NULL;
92 kest_expression *lhs = NULL;
93 kest_expression *rhs = NULL;
94 kest_expression *bin = NULL;
95
96 int precedence;
97 int left_binding_power;
98 int right_binding_power;
99
100
101 int unary_type = kest_expression_token_unary_type(current->data);
102 int infix_type;
103
104 if (token_is_number(current->data))
105 {
107 if (!lhs) return NULL;
108
109 current = current->next;
110 }
111 else if (strcmp(current->data, "(") == 0)
112 {
114 current->next,
115 &current,
116 tokens_end,
117 0,
118 depth + 1);
119
120 if (!lhs) return NULL;
121
122 if (!current || strcmp(current->data, ")") != 0)
123 {
124 kest_parser_error_at(ps, current, "Malformed expression");
125 goto pratt_bail;
126 }
127
128 current = current->next;
129 }
130 else if (unary_type)
131 {
133 current->next,
134 &nt,
135 tokens_end,
137 depth + 1);
138
139 if (!rhs) goto pratt_bail;
140
141 lhs = new_m_expression_unary(unary_type, rhs);
142
143 if (!lhs) goto pratt_bail;
144
145 current = nt;
146 }
147 else if (token_is_name(current->data))
148 {
149 lhs = new_m_expression_reference(current->data);
150
151 current = current->next;
152 }
153 else
154 {
155 kest_parser_error_at(ps, current, "Unexpected \"%s\"", current->data);
156 goto pratt_bail;
157 }
158
159 while (current && current != tokens_end)
160 {
161 infix_type = kest_expression_token_infix_type(current->data);
162
163 if (!infix_type) break;
164
165 precedence = kest_expression_infix_operator_precedence(infix_type);
166 left_binding_power = precedence;
167 right_binding_power = precedence + kest_expression_infix_associativity(infix_type);
168
169 if (left_binding_power < min_binding_power) break;
170
171 current = current->next;
172
174 current,
175 &nt,
176 tokens_end,
177 right_binding_power,
178 depth + 1);
179
180 if (!rhs) goto pratt_bail;
181
182 bin = new_m_expression_binary(infix_type, lhs, rhs);
183
184 if (!bin) goto pratt_bail;
185
186 lhs = bin;
187 current = nt;
188 }
189
190 if (next_token)
191 *next_token = current;
192
193 return lhs;
194
195pratt_bail:
196 // free anything allocated .. ?
197 return NULL;
198}
199
201{
202 kest_token_ll *next_token;
203 kest_expression *expr = kest_parse_expression_rec_pratt(ps, tokens, &next_token, tokens_end, 0, 0);
204
205 int anything = 0;
206 kest_token_ll *check = next_token;
207
208 if (expr)
209 {
211 }
212
213 ps->current_token = next_token;
214
215 return expr;
216}
void kest_parser_error_at(kest_eff_parsing_state *ps, kest_token_ll *token, const char *msg,...)
int kest_expression_infix_operator_precedence(int infix_type)
int kest_expression_token_infix_type(char *token)
kest_expression * kest_parse_expression(kest_eff_parsing_state *ps, kest_token_ll *tokens, kest_token_ll *tokens_end)
int kest_expression_infix_associativity(int infix_type)
int kest_expression_token_unary_type(char *token)
kest_expression * kest_parse_expression_rec_pratt(kest_eff_parsing_state *ps, kest_token_ll *tokens, kest_token_ll **next_token, kest_token_ll *tokens_end, int min_binding_power, int depth)
#define UNARY_PRECEDENCE
#define SUMSUB_PRECEDENCE
#define MULDIV_PRECEDENCE
#define POWER_PRECEDENCE
int kest_expression_detect_constants(kest_expression *expr)
kest_expression * new_m_expression_reference(char *ref_name)
kest_expression * new_m_expression_const(float v)
kest_expression * new_m_expression_unary(int unary_type, kest_expression *rhs)
kest_expression * new_m_expression_binary(int binary_type, kest_expression *arg_1, kest_expression *arg_2)
#define KEST_EXPR_ABS
#define KEST_EXPR_SQR
#define KEST_EXPR_MUL
#define KEST_EXPR_EXP
#define KEST_EXPR_REC_MAX_DEPTH
#define KEST_EXPR_ATAN
#define KEST_EXPR_SUB
#define KEST_EXPR_TANH
#define KEST_EXPR_ACOS
#define KEST_EXPR_COSH
#define KEST_EXPR_SQRT
#define KEST_EXPR_ADD
#define KEST_EXPR_POW
#define KEST_EXPR_SIN
#define KEST_EXPR_ASIN
#define KEST_EXPR_NEG
#define KEST_EXPR_SINH
#define KEST_EXPR_TAN
#define KEST_EXPR_DIV
#define KEST_EXPR_COS
float token_to_float(char *token)
int token_is_name(char *token)
int token_is_number(char *token)
kest_token_ll * current_token
struct kest_token_ll * next