File: | lexer.c |
Warning: | line 122, column 13 Although the value stored to 'type' is used in the enclosing expression, the value is never actually read from 'type' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | #include <stdlib.h> |
2 | #include <assert.h> |
3 | #include <string.h> |
4 | |
5 | #include "lexer.h" |
6 | #include "parserfunc.h" |
7 | #include "mp-equation.h" |
8 | |
9 | static gboolean |
10 | l_check_if_function(LexerState* state) |
11 | { |
12 | gchar* name = pl_get_marked_substring(state->prelexer); |
13 | if(!state->parent->function_is_defined) |
14 | { |
15 | free(name); |
16 | return FALSE(0); |
17 | } |
18 | if ((*(state->parent->function_is_defined))(state->parent, name)) |
19 | { |
20 | free(name); |
21 | return TRUE(!(0)); |
22 | } |
23 | else |
24 | { |
25 | free(name); |
26 | return FALSE(0); |
27 | } |
28 | } |
29 | |
30 | static gboolean |
31 | l_check_if_number(LexerState* state) |
32 | { |
33 | MPNumber tmp; |
34 | int count = 0; |
35 | gchar* text = pl_get_marked_substring(state->prelexer); |
36 | if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0) |
37 | { |
38 | free(text); |
39 | return TRUE(!(0)); |
40 | } |
41 | else |
42 | { |
43 | /* Try to rollback several characters to see, if that yeilds any number. */ |
44 | while(strlen (text) > 0) |
45 | { |
46 | if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0) |
47 | { |
48 | free(text); |
49 | return TRUE(!(0)); |
50 | } |
51 | free(text); |
52 | count++; |
53 | pl_roll_back(state->prelexer); |
54 | text = pl_get_marked_substring(state->prelexer); |
55 | } |
56 | /* Undo all rollbacks. */ |
57 | while(count--) |
58 | pl_get_next_token (state->prelexer); |
59 | free(text); |
60 | return FALSE(0); |
61 | } |
62 | } |
63 | |
64 | /* Insert generated token to the LexerState structure. */ |
65 | static LexerToken* |
66 | l_insert_token(LexerState* state, const LexerTokenType type) |
67 | { |
68 | state->tokens = (LexerToken *) realloc(state->tokens, (state->token_count + 1) * sizeof(LexerToken)); |
69 | assert(state->tokens != NULL)((void) sizeof ((state->tokens != ((void*)0)) ? 1 : 0), __extension__ ({ if (state->tokens != ((void*)0)) ; else __assert_fail ( "state->tokens != NULL", "lexer.c", 69, __extension__ __PRETTY_FUNCTION__ ); })); |
70 | state->tokens[state->token_count].string = pl_get_marked_substring(state->prelexer); |
71 | state->tokens[state->token_count].start_index = state->prelexer->mark_index; |
72 | state->tokens[state->token_count].end_index = state->prelexer->next_index; |
73 | state->tokens[state->token_count].token_type = type; |
74 | state->token_count++; |
75 | return &state->tokens[state->token_count - 1]; |
76 | } |
77 | |
78 | /* Generates next token from pre-lexer stream and call l_insert_token() to insert it at the end. */ |
79 | static LexerToken* |
80 | l_insert_next_token(LexerState* lstate) |
81 | { |
82 | PreLexerState* state = lstate->prelexer; |
83 | LexerTokenType type; |
84 | gchar* tmp; |
85 | pl_set_marker(state); |
86 | /* Ignore all blank spaces. :) */ |
87 | while((type = pl_get_next_token(state)) == PL_SKIP) |
88 | /* Set marker. Beginning of new token. */ |
89 | pl_set_marker(state); |
90 | if(type == T_AND |
91 | ||type == T_OR |
92 | ||type == T_XOR |
93 | ||type == T_NOT |
94 | ||type == T_ADD |
95 | ||type == T_SUBTRACT |
96 | ||type == T_MULTIPLY |
97 | ||type == T_DIV |
98 | ||type == T_L_FLOOR |
99 | ||type == T_R_FLOOR |
100 | ||type == T_L_CEILING |
101 | ||type == T_R_CEILING |
102 | ||type == T_ROOT |
103 | ||type == T_ROOT_3 |
104 | ||type == T_ROOT_4 |
105 | ||type == T_ASSIGN |
106 | ||type == T_L_R_BRACKET |
107 | ||type == T_R_R_BRACKET |
108 | ||type == T_L_S_BRACKET |
109 | ||type == T_R_S_BRACKET |
110 | ||type == T_L_C_BRACKET |
111 | ||type == T_R_C_BRACKET |
112 | ||type == T_ABS |
113 | ||type == T_POWER |
114 | ||type == T_FACTORIAL |
115 | ||type == T_PERCENTAGE) |
116 | { |
117 | return l_insert_token(lstate, type); |
118 | } |
119 | /* [PL_SUPER_MINUS][PL_SUPER_DIGIT]+ */ |
120 | if(type == PL_SUPER_MINUS) |
121 | { |
122 | if((type = pl_get_next_token(state)) != PL_SUPER_DIGIT) |
Although the value stored to 'type' is used in the enclosing expression, the value is never actually read from 'type' | |
123 | { |
124 | /* ERROR: expected PL_SUP_DIGIT */ |
125 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state)); |
126 | free(tmp); |
127 | return l_insert_token(lstate, T_UNKNOWN); |
128 | } |
129 | /* Get all PL_SUPER_DIGITs. */ |
130 | while (pl_get_next_token(state) == PL_SUPER_DIGIT); |
131 | pl_roll_back(state); |
132 | return l_insert_token(lstate, T_NSUP_NUMBER); |
133 | } |
134 | /* [PL_SUPER_DIGIT]+ */ |
135 | if(type == PL_SUPER_DIGIT) |
136 | { |
137 | while(pl_get_next_token(state) == PL_SUPER_DIGIT); |
138 | pl_roll_back(state); |
139 | return l_insert_token(lstate, T_SUP_NUMBER); |
140 | } |
141 | /* [PL_SUB_DIGIT]+ */ |
142 | if(type == PL_SUB_DIGIT) |
143 | { |
144 | while(pl_get_next_token(state) == PL_SUB_DIGIT); |
145 | pl_roll_back(state); |
146 | return l_insert_token(lstate, T_SUB_NUMBER); |
147 | } |
148 | /* [PL_FRACTION] */ |
149 | if(type == PL_FRACTION) |
150 | { |
151 | return l_insert_token(lstate, T_NUMBER); |
152 | } |
153 | if(type == PL_DIGIT) |
154 | { |
155 | while((type = pl_get_next_token(state)) == PL_DIGIT); |
156 | if(type == PL_FRACTION) |
157 | { |
158 | return l_insert_token(lstate, T_NUMBER); |
159 | } |
160 | else if(type == PL_SUB_DIGIT) |
161 | { |
162 | while(pl_get_next_token(state) == PL_SUB_DIGIT); |
163 | pl_roll_back(state); |
164 | return l_insert_token(lstate, T_NUMBER); |
165 | } |
166 | else if(type == PL_DEGREE) |
167 | { |
168 | type = pl_get_next_token(state); |
169 | if(type == PL_DIGIT) |
170 | { |
171 | while((type = pl_get_next_token(state)) == PL_DIGIT); |
172 | if(type == PL_DECIMAL) |
173 | { |
174 | goto ANGLE_NUM_DM_STATE; |
175 | } |
176 | else if(type == PL_MINUTE) |
177 | { |
178 | type = pl_get_next_token(state); |
179 | if(type == PL_DIGIT) |
180 | { |
181 | while((type = pl_get_next_token(state)) == PL_DIGIT); |
182 | if(type == PL_DECIMAL) |
183 | { |
184 | goto ANGLE_NUM_DMS_STATE; |
185 | } |
186 | else if(type == PL_SECOND) |
187 | { |
188 | return l_insert_token(lstate, T_NUMBER); |
189 | } |
190 | else |
191 | { |
192 | /* ERROR: expected PL_SECOND */ |
193 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state)); |
194 | free(tmp); |
195 | return l_insert_token(lstate, T_UNKNOWN); |
196 | } |
197 | } |
198 | else if(type == PL_DECIMAL) |
199 | { |
200 | ANGLE_NUM_DMS_STATE: |
201 | if((type = pl_get_next_token (state)) != PL_DIGIT) |
202 | { |
203 | /* ERROR: expected PL_DIGIT */ |
204 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state)); |
205 | free(tmp); |
206 | return l_insert_token(lstate, T_UNKNOWN); |
207 | } |
208 | while((type = pl_get_next_token(state)) == PL_DIGIT); |
209 | if(type == PL_SECOND) |
210 | { |
211 | return l_insert_token(lstate, T_NUMBER); |
212 | } |
213 | else |
214 | { |
215 | /* ERROR: expected PL_SECOND */ |
216 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state)); |
217 | free(tmp); |
218 | return l_insert_token(lstate, T_UNKNOWN); |
219 | } |
220 | } |
221 | else |
222 | { |
223 | pl_roll_back(state); |
224 | return l_insert_token(lstate, T_NUMBER); |
225 | } |
226 | } |
227 | else |
228 | { |
229 | /* ERROR: expected PL_MINUTE | PL_DIGIT */ |
230 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state)); |
231 | free(tmp); |
232 | return l_insert_token(lstate, T_UNKNOWN); |
233 | } |
234 | } |
235 | else if(type == PL_DECIMAL) |
236 | { |
237 | ANGLE_NUM_DM_STATE: |
238 | if((type = pl_get_next_token(state)) != PL_DIGIT) |
239 | { |
240 | /* ERROR: expected PL_DIGIT */ |
241 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state)); |
242 | free(tmp); |
243 | return l_insert_token(lstate, T_UNKNOWN); |
244 | } |
245 | while((type = pl_get_next_token(state)) == PL_DIGIT); |
246 | if(type == PL_MINUTE) |
247 | { |
248 | return l_insert_token(lstate, T_NUMBER); |
249 | } |
250 | else |
251 | { |
252 | /* ERROR: expected PL_MINUTE */ |
253 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state)); |
254 | free(tmp); |
255 | return l_insert_token(lstate, T_UNKNOWN); |
256 | } |
257 | } |
258 | else |
259 | { |
260 | return l_insert_token(lstate, T_NUMBER); |
261 | } |
262 | } |
263 | else if(type == PL_DECIMAL) |
264 | { |
265 | goto DECIMAL_STATE; |
266 | } |
267 | else if(type == PL_HEX) |
268 | { |
269 | goto HEX_DEC_STATE; |
270 | } |
271 | else |
272 | { |
273 | pl_roll_back(state); |
274 | return l_insert_token(lstate, T_NUMBER); |
275 | } |
276 | } |
277 | if(type == PL_DECIMAL) |
278 | { |
279 | DECIMAL_STATE: |
280 | type = pl_get_next_token(state); |
281 | if(type == PL_DIGIT) |
282 | { |
283 | while((type = pl_get_next_token(state)) == PL_DIGIT); |
284 | if(type == PL_DEGREE) |
285 | { |
286 | return l_insert_token(lstate, T_NUMBER); |
287 | } |
288 | else if(type == PL_HEX) |
289 | { |
290 | goto DECIMAL_HEX_STATE; |
291 | } |
292 | else if(type == PL_SUB_DIGIT) |
293 | { |
294 | while(pl_get_next_token(state) == PL_SUB_DIGIT); |
295 | pl_roll_back(state); |
296 | return l_insert_token(lstate, T_NUMBER); |
297 | } |
298 | else |
299 | { |
300 | pl_roll_back(state); |
301 | return l_insert_token(lstate, T_NUMBER); |
302 | } |
303 | } |
304 | else if(type == PL_HEX) |
305 | { |
306 | goto DECIMAL_HEX_STATE; |
307 | } |
308 | else |
309 | { |
310 | /* ERROR: expected PL_DIGIT | PL_HEX */ |
311 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state)); |
312 | free(tmp); |
313 | return l_insert_token(lstate, T_UNKNOWN); |
314 | } |
315 | } |
316 | if(type == PL_HEX) |
317 | { |
318 | while((type = pl_get_next_token(state)) == PL_HEX); |
319 | if(type == PL_DIGIT) |
320 | { |
321 | HEX_DEC_STATE: |
322 | while(1) |
323 | { |
324 | type = pl_get_next_token(state); |
325 | if(type == PL_DIGIT || type == PL_HEX) |
326 | { |
327 | continue; |
328 | } |
329 | else if(type == PL_DECIMAL) |
330 | { |
331 | goto DECIMAL_HEX_STATE; |
332 | } |
333 | else if(type == PL_SUB_DIGIT) |
334 | { |
335 | while(pl_get_next_token(state) == PL_SUB_DIGIT); |
336 | pl_roll_back(state); |
337 | return l_insert_token(lstate, T_NUMBER); |
338 | } |
339 | else |
340 | { |
341 | if(l_check_if_number(lstate)) |
342 | return l_insert_token(lstate, T_NUMBER); |
343 | /* ERROR: expected PL_DECIMAL | PL_DIGIT | PL_HEX */ |
344 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state)); |
345 | free(tmp); |
346 | return l_insert_token(lstate, T_UNKNOWN); |
347 | } |
348 | } |
349 | } |
350 | else if(type == PL_DECIMAL) |
351 | { |
352 | DECIMAL_HEX_STATE: |
353 | type = pl_get_next_token(state); |
354 | if(!(type == PL_DIGIT || type == PL_HEX)) |
355 | { |
356 | /* ERROR: expected PL_DIGIT | PL_HEX */ |
357 | set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state)); |
358 | free(tmp); |
359 | return l_insert_token(lstate, T_UNKNOWN); |
360 | } |
361 | while(1) |
362 | { |
363 | type = pl_get_next_token(state); |
364 | if(type == PL_DIGIT || type == PL_HEX) |
365 | { |
366 | continue; |
367 | } |
368 | else if(type == PL_SUB_DIGIT) |
369 | { |
370 | while(pl_get_next_token(state) == PL_SUB_DIGIT); |
371 | pl_roll_back(state); |
372 | return l_insert_token(lstate, T_NUMBER); |
373 | } |
374 | else |
375 | { |
376 | pl_roll_back(state); |
377 | return l_insert_token(lstate, T_NUMBER); |
378 | } |
379 | } |
380 | } |
381 | else if(type == PL_SUB_DIGIT) |
382 | { |
383 | while(pl_get_next_token(state) == PL_SUB_DIGIT); |
384 | pl_roll_back(state); |
385 | if(l_check_if_number(lstate)) |
386 | { |
387 | /* NUMBER */ |
388 | return l_insert_token(lstate, T_NUMBER); |
389 | } |
390 | else |
391 | { |
392 | /* VARIABLE */ |
393 | if(l_check_if_function(lstate)) |
394 | { |
395 | return l_insert_token(lstate, T_FUNCTION); |
396 | } |
397 | else |
398 | { |
399 | return l_insert_token(lstate, T_VARIABLE); |
400 | } |
401 | } |
402 | } |
403 | else if(type == PL_LETTER) |
404 | { |
405 | goto LETTER_STATE; |
406 | } |
407 | else |
408 | { |
409 | pl_roll_back(state); |
410 | if(l_check_if_number(lstate)) |
411 | { |
412 | /* NUMBER */ |
413 | return l_insert_token(lstate, T_NUMBER); |
414 | } |
415 | else |
416 | { |
417 | /* VARIABLE */ |
418 | if(l_check_if_function(lstate)) |
419 | { |
420 | return l_insert_token(lstate, T_FUNCTION); |
421 | } |
422 | else |
423 | { |
424 | return l_insert_token(lstate, T_VARIABLE); |
425 | } |
426 | } |
427 | } |
428 | } |
429 | if(type == PL_LETTER) |
430 | { |
431 | LETTER_STATE: |
432 | while(1) |
433 | { |
434 | type = pl_get_next_token(state); |
435 | if(type == PL_LETTER || type == PL_HEX) |
436 | { |
437 | continue; |
438 | } |
439 | else if(type == PL_SUB_DIGIT) |
440 | { |
441 | while(pl_get_next_token(state) == PL_SUB_DIGIT); |
442 | pl_roll_back(state); |
443 | tmp = g_ascii_strdown(pl_get_marked_substring(state), -1); |
444 | if(g_strcmp0(tmp, "mod") == 0) |
445 | { |
446 | return l_insert_token(lstate, T_MOD); |
447 | } |
448 | if(g_strcmp0(tmp, "and") == 0) |
449 | { |
450 | return l_insert_token(lstate, T_AND); |
451 | } |
452 | if(g_strcmp0(tmp, "or") == 0) |
453 | { |
454 | return l_insert_token(lstate, T_OR); |
455 | } |
456 | if(g_strcmp0(tmp, "xor") == 0) |
457 | { |
458 | return l_insert_token(lstate, T_XOR); |
459 | } |
460 | if(g_strcmp0(tmp, "not") == 0) |
461 | { |
462 | return l_insert_token(lstate, T_NOT); |
463 | } |
464 | if(g_strcmp0(tmp, "in") == 0) |
465 | { |
466 | return l_insert_token(lstate, T_IN); |
467 | } |
468 | if(l_check_if_function(lstate)) |
469 | { |
470 | return l_insert_token(lstate, T_FUNCTION); |
471 | } |
472 | else |
473 | { |
474 | return l_insert_token(lstate, T_VARIABLE); |
475 | } |
476 | } |
477 | else |
478 | { |
479 | pl_roll_back(state); |
480 | tmp = g_ascii_strdown(pl_get_marked_substring(state), -1); |
481 | if(g_strcmp0(tmp, "mod") == 0) |
482 | { |
483 | return l_insert_token(lstate, T_MOD); |
484 | } |
485 | if(g_strcmp0(tmp, "and") == 0) |
486 | { |
487 | return l_insert_token(lstate, T_AND); |
488 | } |
489 | if(g_strcmp0(tmp, "or") == 0) |
490 | { |
491 | return l_insert_token(lstate, T_OR); |
492 | } |
493 | if(g_strcmp0(tmp, "xor") == 0) |
494 | { |
495 | return l_insert_token(lstate, T_XOR); |
496 | } |
497 | if(g_strcmp0(tmp, "not") == 0) |
498 | { |
499 | return l_insert_token(lstate, T_NOT); |
500 | } |
501 | if(g_strcmp0(tmp, "in") == 0) |
502 | { |
503 | return l_insert_token(lstate, T_IN); |
504 | } |
505 | if(l_check_if_function(lstate)) |
506 | { |
507 | return l_insert_token(lstate, T_FUNCTION); |
508 | } |
509 | else |
510 | { |
511 | return l_insert_token(lstate, T_VARIABLE); |
512 | } |
513 | } |
514 | } |
515 | } |
516 | if(type == PL_EOS) |
517 | { |
518 | return l_insert_token(lstate, PL_EOS); |
519 | } |
520 | /* ERROR: Unexpected token.. X( */ |
521 | set_error(lstate->parent, PARSER_ERR_INVALID, tmp = pl_get_marked_substring(state)); |
522 | free(tmp); |
523 | return l_insert_token(lstate, T_UNKNOWN); |
524 | } |
525 | |
526 | /* Call l_insert_next_token() as many times as needed to completely tokenize the string. */ |
527 | void |
528 | l_insert_all_tokens(LexerState* state) |
529 | { |
530 | LexerToken* token; |
531 | while(1) |
532 | { |
533 | token = l_insert_next_token(state); |
534 | assert(token != NULL)((void) sizeof ((token != ((void*)0)) ? 1 : 0), __extension__ ({ if (token != ((void*)0)) ; else __assert_fail ("token != NULL" , "lexer.c", 534, __extension__ __PRETTY_FUNCTION__); })); |
535 | if(token->token_type == PL_EOS) |
536 | { |
537 | break; |
538 | } |
539 | } |
540 | } |
541 | |
542 | /* Create a lexer state from given input string. This will take care of pre-lexer state. */ |
543 | LexerState* |
544 | l_create_lexer(const gchar* input, struct parser_state* parent) |
545 | { |
546 | LexerState* ret; |
547 | ret = (LexerState *) malloc(sizeof(LexerState)); |
548 | assert(ret != NULL)((void) sizeof ((ret != ((void*)0)) ? 1 : 0), __extension__ ( { if (ret != ((void*)0)) ; else __assert_fail ("ret != NULL", "lexer.c", 548, __extension__ __PRETTY_FUNCTION__); })); |
549 | ret->prelexer = pl_create_scanner(input); |
550 | ret->tokens = NULL((void*)0); |
551 | ret->token_count = 0; |
552 | ret->next_token = 0; |
553 | ret->parent = parent; |
554 | return ret; |
555 | } |
556 | |
557 | /* Destroy lexer state and free memory. */ |
558 | void |
559 | l_destroy_lexer(LexerState* state) |
560 | { |
561 | int l; |
562 | pl_destroy_scanner(state->prelexer); |
563 | for(l = 0; l < state->token_count; l++) |
564 | { |
565 | free(state->tokens[l].string); |
566 | } |
567 | free(state->tokens); |
568 | free(state); |
569 | } |
570 | |
571 | /* Get next token interface. Will be called by parser to get pointer to next token in token stream. */ |
572 | LexerToken* |
573 | l_get_next_token(LexerState* state) |
574 | { |
575 | /* Return PL_EOS token after token stream reaches to its end. */ |
576 | if(state->next_token >= state->token_count) |
577 | return &state->tokens[state->token_count - 1]; |
578 | return &state->tokens[state->next_token++]; |
579 | } |
580 | |
581 | /* Roll back one lexer token. */ |
582 | void |
583 | l_roll_back(LexerState* state) |
584 | { |
585 | if(state->next_token > 0) |
586 | state->next_token--; |
587 | } |