Bug Summary

File:app/main/parser.cpp
Location:line 61, column 9
Description:Potential leak of memory pointed to by 'result'

Annotated Source Code

1/*
2 * Copyright (c) 2015-2017 Carsten Sonne Larsen <cs@innolan.dk>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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
39Parser::Parser(const char *input)
40{
41 lexer = new Lexer(input);
42}
43
44Parser::~Parser()
45{
46 delete lexer;
47}
48
49SyntaxNode* 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) {
1
Taking true branch
75 if (result != NOMEM0) {
2
Taking true branch
76 delete result;
77 }
78
79 result = new ErrorNode(lexer->GetInput(), token->GetPos());
3
Memory is allocated
80 if (block != NOMEM0) {
4
Taking false branch
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
95SyntaxNode* 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// -------------- Recursive-descent logic --------------
122// -----------------------------------------------------
123
124SyntaxNode* 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
194SyntaxNode* Parser::ParseDefault()
195{
196 Token *temp = token;
197
198 // Peek tokens
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 // Restart parsing
206 syntaxError = -1;
207 errorNode = NOMEM0;
208 token = temp;
209
210 if (funcdef) {
211 return ParseFunctionDef();
212 } else {
213 return ParseEvaluation();
214 }
215}
216
217SyntaxNode* 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
232ExpressionNode* Parser::ParseExpression ()
233{
234 return ParseAddSubstract();
235}
236
237ExpressionNode* 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
256ExpressionNode* 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
275ExpressionNode* 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
289ExpressionNode* 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
304ExpressionNode* 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
335ExpressionNode* 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
379ExpressionNode* 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// ------------------- Token logic ---------------------
399// -----------------------------------------------------
400
401void Parser::GetToken ()
402{
403 token = (token == NOMEM0 ? lexer->GetFirstToken() : token->GetNextToken());
404}
405
406void Parser::PutToken()
407{
408 token = token->GetLastToken();
409}
410
411bool 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// ----------------- Statement logic -------------------
424// -----------------------------------------------------
425
426SyntaxNode* 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 // TODO: Move logic to FunctionDefinitionNode
453 return new FunctionDefinitionNode();
454}
455
456SyntaxNode* 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
470SyntaxNode* 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
494SyntaxNode* 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
508SyntaxNode* 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
531SyntaxNode* 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
588SyntaxNode* 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
618SyntaxNode* 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
629SyntaxNode* 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
640SyntaxNode* 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}