1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | #include "clib.h" |
28 | #include "lib/numb.h" |
29 | #include "lib/real.h" |
30 | #include "lib/cplex.h" |
31 | #include "main/parser.h" |
32 | #include "main/values.h" |
33 | #include "main/operators.h" |
34 | #include "main/functions.h" |
35 | #include "main/statements.h" |
36 | #include "localize/text.h" |
37 | #include "system/program.h" |
38 | |
39 | Parser::Parser(const char *input) |
40 | { |
41 | lexer = new Lexer(input); |
42 | } |
43 | |
44 | Parser::~Parser() |
45 | { |
46 | delete lexer; |
47 | } |
48 | |
49 | SyntaxNode* Parser::Parse() |
50 | { |
51 | lexer->Tokenize(); |
52 | token = NOMEM0; |
53 | |
54 | StatementBlockNode *block = NOMEM0; |
55 | SyntaxNode *result; |
56 | Token *current; |
57 | |
58 | do { |
| 5 | | Loop condition is true. Execution continues on line 59 | |
|
59 | result = TryParseStatement(); |
60 | |
61 | GetToken(); |
| 6 | | Potential leak of memory pointed to by 'result' |
|
62 | if (token->symbol == symdelimiter || (token->symbol == symend && block != NOMEM0)) { |
63 | if (block == NOMEM0) { |
64 | block = new StatementBlockNode(); |
65 | } |
66 | |
67 | if (result != NOMEM0) { |
68 | block->Add(result); |
69 | } |
70 | |
71 | while (token->symbol == symdelimiter) { |
72 | GetToken(); |
73 | } |
74 | } else if (token->symbol != symend) { |
| |
75 | if (result != NOMEM0) { |
| |
76 | delete result; |
77 | } |
78 | |
79 | result = new ErrorNode(lexer->GetInput(), token->GetPos()); |
| |
80 | if (block != NOMEM0) { |
| |
81 | block->Add(result); |
82 | } |
83 | |
84 | GetToken(); |
85 | } |
86 | |
87 | current = token; |
88 | PutToken(); |
89 | } while (current->symbol != symend); |
90 | |
91 | return block != NOMEM0 ? block : |
92 | result != NOMEM0 ? result : new EmptyStatement();; |
93 | } |
94 | |
95 | SyntaxNode* Parser::TryParseStatement() |
96 | { |
97 | GetToken(); |
98 | if(token->symbol == symend || token->symbol == symdelimiter) { |
99 | PutToken(); |
100 | return NOMEM0; |
101 | } |
102 | PutToken(); |
103 | |
104 | errorNode = NOMEM0; |
105 | syntaxError = -1; |
106 | SyntaxNode *result = ParseStatement(); |
107 | |
108 | if (errorNode == NOMEM0 && syntaxError != -1) { |
109 | errorNode = new ErrorNode(lexer->GetInput(), syntaxError); |
110 | } |
111 | |
112 | if (errorNode != NOMEM0) { |
113 | delete result; |
114 | result = errorNode; |
115 | } |
116 | |
117 | return result; |
118 | } |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | SyntaxNode* Parser::ParseStatement() |
125 | { |
126 | SyntaxNode* res = NOMEM0; |
127 | |
128 | GetToken(); |
129 | switch (token->symbol) { |
130 | case symhelp: |
131 | res = ParseHelpStatement(); |
132 | break; |
133 | case symdelete: |
134 | res = ParseDeleteStatement(); |
135 | break; |
136 | case symdef: |
137 | res = ParseFunctionDef(); |
138 | break; |
139 | case symlist: |
140 | res = ParseListStatement(); |
141 | break; |
142 | case symshow: |
143 | case symload: |
144 | case symsave: |
145 | case symexecute: |
146 | res = ParseFileStatement(); |
147 | break; |
148 | case syminput: |
149 | case symoutput: |
150 | res = ParseNumeralStatement(); |
151 | break; |
152 | case symprompt: |
153 | res = ParsePromptStatement(); |
154 | break; |
155 | case symprefs: |
156 | res = ParsePrefsStatement(); |
157 | break; |
158 | case symdigits: |
159 | res = ParseDigistStatement(); |
160 | break; |
161 | case symdraw: |
162 | case symplot: |
163 | res = ParseDrawStatement(); |
164 | break; |
165 | case symversion: |
166 | res = new VersionStatement(); |
167 | break; |
168 | case symexit: |
169 | res = new ExitStatement(); |
170 | break; |
171 | case symclear: |
172 | res = new ClearStatement(); |
173 | break; |
174 | case symmem: |
175 | res = new MemoryStatement(); |
176 | break; |
177 | case symvariable: |
178 | res = new ListVariablesStatement(); |
179 | break; |
180 | case symfunction: |
181 | res = new ListFunctionsStatement(); |
182 | break; |
183 | case symeval: |
184 | res = new EvalStatement(ParseExpression()); |
185 | break; |
186 | default: |
187 | PutToken(); |
188 | res = ParseDefault(); |
189 | } |
190 | |
191 | return res; |
192 | } |
193 | |
194 | SyntaxNode* Parser::ParseDefault() |
195 | { |
196 | Token *temp = token; |
197 | |
198 | |
199 | bool funcdef = Expect(symident); |
200 | funcdef = funcdef && Expect(symlparen); |
201 | funcdef = funcdef && Expect(symident); |
202 | funcdef = funcdef && Expect(symrparen); |
203 | funcdef = funcdef && Expect(symassign); |
204 | |
205 | |
206 | syntaxError = -1; |
207 | errorNode = NOMEM0; |
208 | token = temp; |
209 | |
210 | if (funcdef) { |
211 | return ParseFunctionDef(); |
212 | } else { |
213 | return ParseEvaluation(); |
214 | } |
215 | } |
216 | |
217 | SyntaxNode* Parser::ParseEvaluation() |
218 | { |
219 | ExpressionNode *exp = ParseExpression(); |
220 | if (exp == NOMEM0) { |
221 | return NOMEM0; |
222 | } |
223 | |
224 | StatementNode *sta = new EvalStatement(exp); |
225 | if (exp->IsSilent()) { |
226 | sta = new SilentStatement(sta); |
227 | } |
228 | |
229 | return sta; |
230 | } |
231 | |
232 | ExpressionNode* Parser::ParseExpression () |
233 | { |
234 | return ParseAddSubstract(); |
235 | } |
236 | |
237 | ExpressionNode* Parser::ParseAddSubstract () |
238 | { |
239 | ExpressionNode* node = ParseFactor (); |
240 | |
241 | GetToken(); |
242 | while (token->symbol == symplus || token->symbol == symminus) { |
243 | if (token->symbol == symplus) { |
244 | node = new AdditionNode (node, ParseFactor ()); |
245 | } else if (token->symbol == symminus) { |
246 | node = new SubtractionNode (node, ParseFactor ()); |
247 | } |
248 | |
249 | GetToken(); |
250 | } |
251 | |
252 | PutToken(); |
253 | return node; |
254 | } |
255 | |
256 | ExpressionNode* Parser::ParseFactor () |
257 | { |
258 | ExpressionNode* node = ParsePower (); |
259 | |
260 | GetToken(); |
261 | while (token->symbol == symtimes || token->symbol == symslash) { |
262 | if (token->symbol == symtimes) { |
263 | node = new MultiplicationNode (node, ParsePower ()); |
264 | } else if (token->symbol == symslash) { |
265 | node = new DivisionNode (node, ParsePower ()); |
266 | } |
267 | |
268 | GetToken(); |
269 | } |
270 | |
271 | PutToken(); |
272 | return node; |
273 | } |
274 | |
275 | ExpressionNode* Parser::ParsePower() |
276 | { |
277 | ExpressionNode* node = ParseUnary (); |
278 | |
279 | GetToken(); |
280 | while (token->symbol == sympower) { |
281 | node = new PowerNode (node, ParseUnary ()); |
282 | GetToken (); |
283 | } |
284 | |
285 | PutToken(); |
286 | return node; |
287 | } |
288 | |
289 | ExpressionNode* Parser::ParseUnary() |
290 | { |
291 | ExpressionNode* node; |
292 | |
293 | GetToken(); |
294 | if (token->symbol == symminus) { |
295 | node = new UnaryNode(ParseAtomic ()); |
296 | } else { |
297 | PutToken(); |
298 | node = ParseAtomic(); |
299 | } |
300 | |
301 | return node; |
302 | } |
303 | |
304 | ExpressionNode* Parser::ParseAtomic () |
305 | { |
306 | ExpressionNode* node; |
307 | |
308 | GetToken(); |
309 | if (token->symbol == symlparen) { |
310 | node = ParseExpression(); |
311 | Expect(symrparen); |
312 | } else if (token->symbol == symabsolute) { |
313 | node = new AbsoluteNode(ParseExpression()); |
314 | Expect(symabsolute); |
315 | } else if (token->symbol == symident) { |
316 | node = ParseIdent(); |
317 | } else if (token->symbol == sympi) { |
318 | node = new PiNode(); |
319 | } else if (token->symbol == syme) { |
320 | node = new EulersNumberNode(); |
321 | } else if (token->symbol == symi) { |
322 | node = new ComplexiNode(); |
323 | } else if (token->symbol == symins) { |
324 | node = new InsVariableNode(); |
325 | } else if (token->symbol == symnumber) { |
326 | node = ParseNumber(); |
327 | } else { |
328 | node = new NumericValueNode(); |
329 | syntaxError = token->GetPos(); |
330 | } |
331 | |
332 | return node; |
333 | } |
334 | |
335 | ExpressionNode* Parser::ParseIdent() |
336 | { |
337 | ExpressionNode *node; |
338 | Token *identToken = token; |
339 | |
340 | GetToken(); |
341 | if (token->symbol == symlparen) { |
342 | ExpressionNode* parameter = ParseExpression(); |
343 | Expect(symrparen); |
344 | node = Program->Functions->GetFunctionCall(identToken->GetText(), parameter); |
345 | |
346 | if (node == NOMEM0) { |
347 | errorNode = new ErrorNode( |
348 | lexer->GetInput(), |
349 | HELPFUNNDEFProgram->Language->GetText(12), |
350 | identToken->GetText(), |
351 | identToken->GetPos()); |
352 | |
353 | delete parameter; |
354 | node = new NumericValueNode(); |
355 | } |
356 | } else if (token->symbol == symassign) { |
357 | Variable* var = Program->Variables->CreateVariable(identToken->GetText()); |
358 | node = new AssignmentNode(new VariableNode(var), ParseExpression()); |
359 | } else { |
360 | PutToken(); |
361 | Variable* var = Program->Variables->GetVariable(token->GetText()); |
362 | |
363 | if (var == NOMEM0) { |
364 | errorNode = new ErrorNode( |
365 | lexer->GetInput(), |
366 | HELPVARNDEFProgram->Language->GetText(11), |
367 | identToken->GetText(), |
368 | identToken->GetPos()); |
369 | |
370 | node = new NumericValueNode(); |
371 | } else { |
372 | node = new VariableNode(var); |
373 | } |
374 | } |
375 | |
376 | return node; |
377 | } |
378 | |
379 | ExpressionNode* Parser::ParseNumber() |
380 | { |
381 | const char *a = token->GetText(); |
382 | Number *number = NOMEM0; |
383 | |
384 | GetToken(); |
385 | if (token->symbol == symi) { |
386 | Number *imag = Program->Input->Parse(a); |
387 | number = new ComplexNumber(0.0, imag->GetRealValue()); |
388 | delete imag; |
389 | } else { |
390 | PutToken(); |
391 | number = Program->Input->Parse(a); |
392 | } |
393 | |
394 | return new NumericValueNode (number); |
395 | } |
396 | |
397 | |
398 | |
399 | |
400 | |
401 | void Parser::GetToken () |
402 | { |
403 | token = (token == NOMEM0 ? lexer->GetFirstToken() : token->GetNextToken()); |
404 | } |
405 | |
406 | void Parser::PutToken() |
407 | { |
408 | token = token->GetLastToken(); |
409 | } |
410 | |
411 | bool Parser::Expect(Symbol symbol) |
412 | { |
413 | GetToken(); |
414 | if (token->symbol != symbol) { |
415 | syntaxError = token->GetPos(); |
416 | return false; |
417 | } else { |
418 | return true; |
419 | } |
420 | } |
421 | |
422 | |
423 | |
424 | |
425 | |
426 | SyntaxNode* Parser::ParseFunctionDef() |
427 | { |
428 | Expect(symident); |
429 | Token* funcToken = token; |
430 | Expect(symlparen); |
431 | Expect(symident); |
432 | Token* funcVariable = token; |
433 | Expect(symrparen); |
434 | Expect(symassign); |
435 | |
436 | if (Program->Functions->IsSystemFunction(funcToken->GetText())) { |
437 | errorNode = new ErrorNode( |
438 | lexer->GetInput(), |
439 | HELPFUNRDEFProgram->Language->GetText(13), |
440 | funcToken->GetText(), |
441 | funcToken->GetPos()); |
442 | |
443 | return NOMEM0; |
444 | } |
445 | |
446 | UserFunction* function = Program->Functions->GetFunctionDef(funcToken->GetText()); |
447 | Variable* variable = function->CreateVariable(funcVariable->GetText()); |
448 | Program->Variables->InsertTemporaryVariable(variable); |
449 | function->SetExpression(ParseExpression()); |
450 | Program->Variables->RemoveTemporaryVariable(); |
451 | |
452 | |
453 | return new FunctionDefinitionNode(); |
454 | } |
455 | |
456 | SyntaxNode* Parser::ParseHelpStatement() |
457 | { |
458 | GetToken(); |
459 | |
460 | if (token->symbol == symdelimiter || token->symbol == symend) { |
461 | PutToken(); |
462 | return new HelpStatement(); |
463 | } else if (token->symbol == symident) { |
464 | return new HelpStatement(token->GetText()); |
465 | } else { |
466 | return new HelpStatement(token->symbol); |
467 | } |
468 | } |
469 | |
470 | SyntaxNode* Parser::ParseDeleteStatement() |
471 | { |
472 | GetToken(); |
473 | if (token->symbol == symvariable || token->symbol == symfunction) { |
474 | return new DeleteStatement(token->symbol); |
475 | } else if (token->symbol != symident) { |
476 | syntaxError = token->GetPos(); |
477 | return NOMEM0; |
478 | } |
479 | |
480 | Token *identToken = token; |
481 | |
482 | GetToken(); |
483 | if (token->symbol == symlparen) { |
484 | Expect(symident); |
485 | Token *parameter = token; |
486 | Expect(symrparen); |
487 | return new DeleteStatement(identToken->GetText(), parameter->GetText()); |
488 | } else { |
489 | PutToken(); |
490 | return new DeleteStatement(token->GetText()); |
491 | } |
492 | } |
493 | |
494 | SyntaxNode* Parser::ParseListStatement() |
495 | { |
496 | GetToken(); |
497 | if (token->symbol == symqident) |
498 | return new ListStatement(token->GetText()); |
499 | else if (token->symbol == symend || symdelimiter) { |
500 | PutToken(); |
501 | return new ListStatement(); |
502 | } else { |
503 | syntaxError = token->GetPos(); |
504 | return NOMEM0; |
505 | } |
506 | } |
507 | |
508 | SyntaxNode* Parser::ParseFileStatement() |
509 | { |
510 | Token *statement = token; |
511 | |
512 | Expect(symqident); |
513 | Token *identToken = token; |
514 | |
515 | if (statement->symbol == symload) { |
516 | return new LoadStatement(identToken->GetText()); |
517 | } else if (statement->symbol == symsave) { |
518 | return new SaveStatement(identToken->GetText()); |
519 | } else if (statement->symbol == symexecute) { |
520 | return new ExecuteStatement(identToken->GetText()); |
521 | } else if (statement->symbol == symshow) { |
522 | return new ShowStatement(identToken->GetText()); |
523 | } else { |
524 | return new ErrorNode( |
525 | lexer->GetInput(), |
526 | HELPUERRORProgram->Language->GetText(10), EMPTYSTRING"", |
527 | statement->GetPos()); |
528 | } |
529 | } |
530 | |
531 | SyntaxNode* Parser::ParseNumeralStatement() |
532 | { |
533 | Token *statement = token; |
534 | unsigned int base; |
535 | |
536 | GetToken(); |
537 | switch (token->symbol) { |
538 | case symend: |
539 | case symdelimiter: |
540 | PutToken(); |
541 | return (statement->symbol == syminput) ? |
542 | (SyntaxNode*)new InputStatement() : |
543 | (SyntaxNode*)new OutputStatement(); |
544 | case symbin: |
545 | base = 2; |
546 | break; |
547 | case symoct: |
548 | base = 8; |
549 | break; |
550 | case symdec: |
551 | base = 10; |
552 | break; |
553 | case symhex: |
554 | base = 16; |
555 | break; |
556 | default: |
557 | base = 0; |
558 | } |
559 | |
560 | if (base == 0 && token->symbol != symnumber) { |
561 | syntaxError = token->GetPos(); |
562 | return NOMEM0; |
563 | } |
564 | |
565 | if (base == 0) { |
566 | NumeralSystem *nsys = new DecimalSystem(0); |
567 | Number *number = nsys->Parse(token->GetText()); |
568 | base = number->GetIntegerValue(); |
569 | delete number; |
570 | delete nsys; |
571 | |
572 | if (base < 2 || base > 32) { |
573 | errorNode = new ErrorNode( |
574 | lexer->GetInput(), |
575 | HELPPNUMERAProgram->Language->GetText(14), |
576 | token->GetText(), |
577 | token->GetPos()); |
578 | |
579 | return NOMEM0; |
580 | } |
581 | } |
582 | |
583 | return (statement->symbol == syminput) ? |
584 | (SyntaxNode*)new InputStatement(base) : |
585 | (SyntaxNode*)new OutputStatement(base); |
586 | } |
587 | |
588 | SyntaxNode* Parser::ParseDigistStatement() |
589 | { |
590 | GetToken(); |
591 | if (token->symbol == symdelimiter || token->symbol == symend) { |
592 | PutToken(); |
593 | return new DigitsStatement(); |
594 | } else if (token->symbol != symnumber) { |
595 | syntaxError = token->GetPos(); |
596 | return NOMEM0; |
597 | } |
598 | |
599 | NumeralSystem *nsys = new DecimalSystem(0); |
600 | Number *number = nsys->Parse(token->GetText()); |
601 | int digits = number->GetIntegerValue(); |
602 | delete number; |
603 | delete nsys; |
604 | |
605 | if (digits < 0 || digits > 15) { |
606 | errorNode = new ErrorNode( |
607 | lexer->GetInput(), |
608 | HELPPDIGITSProgram->Language->GetText(15), |
609 | token->GetText(), |
610 | token->GetPos()); |
611 | |
612 | return NOMEM0; |
613 | } |
614 | |
615 | return new DigitsStatement(digits); |
616 | } |
617 | |
618 | SyntaxNode* Parser::ParsePromptStatement() |
619 | { |
620 | GetToken(); |
621 | if (token->symbol == symqident) { |
622 | return new PromptStatement(token->GetText()); |
623 | } |
624 | |
625 | PutToken(); |
626 | return NOMEM0; |
627 | } |
628 | |
629 | SyntaxNode* Parser::ParsePrefsStatement() |
630 | { |
631 | GetToken(); |
632 | if (token->symbol == symload || token->symbol == symsave) { |
633 | return new PrefsStatement(token->symbol); |
634 | } |
635 | |
636 | PutToken(); |
637 | return new PrefsStatement();; |
638 | } |
639 | |
640 | SyntaxNode* Parser::ParseDrawStatement() |
641 | { |
642 | Token *statement = token; |
643 | |
644 | Expect(symident); |
645 | Token *identToken = token; |
646 | Expect(symlparen); |
647 | Expect(symident); |
648 | Token *paramToken = token; |
649 | Expect(symrparen); |
650 | |
651 | if (statement->symbol == symplot) { |
652 | return new PlotStatement(identToken->GetText(), paramToken->GetText()); |
653 | } else { |
654 | return new DrawStatement(identToken->GetText(), paramToken->GetText()); |
655 | } |
656 | } |