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