Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
evalExp.C
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
262# include <cctype>
263# include <cstring>
264# include <cstdlib>
265# include <iostream>
266# include <tclap/CmdLine.h>
267# include <tpl_arrayStack.H>
268
269using namespace std;
270using namespace Aleph;
271
273
281Token_Type lexer(char *& str, size_t & len)
282{
283 str += len;
284 len = 1;
285
286 while (isblank(*str))
287 str++;
288
289 switch (*str)
290 {
291 case '(': return Lpar;
292 case ')': return Rpar;
293 case '+':
294 case '-':
295 case '*':
296 case '/': return Operator;
297 case '\0': return End;
298 }
299
300 if (not isdigit(*str))
301 return Error;
302
303 char* base = str + 1;
304 while (isdigit(*base++))
305 len++;
306
307 return Value;
308}
309
313char * str_to_token(const char * token_str, const size_t & len)
314{
315 static char buffer[256];
316 strncpy(buffer, token_str, len);
317 buffer[len] = '\0';
318 return buffer;
319}
320
326unsigned precedence(const char & op)
327{
328 switch (op)
329 {
330 case '$': return 0; // Stack bottom marker
331 case '(': return 1;
332 case '+':
333 case '-': return 2;
334 case '/':
335 case '*': return 3;
336 default:
337 cerr << "Invalid operator: " << op << endl;
338 exit(1);
339 }
340}
341
346{
347 if (op_stack.size() == 0)
348 {
349 cerr << "Error: operator stack empty" << endl;
350 exit(1);
351 }
352 if (val_stack.size() < 2)
353 {
354 cerr << "Error: not enough operands" << endl;
355 exit(1);
356 }
357
358 const char the_operator = op_stack.pop();
359 const int right_operand = val_stack.pop();
360 const int left_operand = val_stack.pop();
361 int result;
362
363 switch (the_operator)
364 {
365 case '+': result = left_operand + right_operand; break;
366 case '-': result = left_operand - right_operand; break;
367 case '*': result = left_operand * right_operand; break;
368 case '/':
369 if (right_operand == 0)
370 {
371 cerr << "Error: division by zero" << endl;
372 exit(1);
373 }
374 result = left_operand / right_operand;
375 break;
376 default:
377 cerr << "Invalid operator: " << the_operator << endl;
378 exit(1);
379 }
380
381 val_stack.push(result);
382}
383
390int eval(char* input)
391{
394 size_t token_len = 0;
395
396 op_stack.push('$'); // Stack bottom marker
397
398 while (true)
399 {
400 switch (lexer(input, token_len))
401 {
402 case Value:
403 {
404 const int operand = atoi(str_to_token(input, token_len));
406 break;
407 }
408
409 case Lpar:
411 break;
412
413 case Operator:
414 while (precedence(op_stack.top()) >= precedence(*input))
417 break;
418
419 case Rpar:
420 while (op_stack.top() != '(')
421 {
422 if (op_stack.top() == '$')
423 {
424 cerr << "Error: mismatched parentheses" << endl;
425 exit(1);
426 }
428 }
429 op_stack.pop(); // Remove the '('
430 break;
431
432 case End:
433 while (op_stack.top() != '$')
435 op_stack.pop(); // Remove '$'
436
437 if (val_stack.size() != 1 or op_stack.size() != 0)
438 {
439 cerr << "Error: malformed expression" << endl;
440 exit(1);
441 }
442 return val_stack.pop();
443
444 case Error:
445 default:
446 cerr << "Error: invalid token at position" << endl;
447 exit(1);
448 }
449 }
450}
451
452int main(int argc, char** argv)
453{
454 try
455 {
456 TCLAP::CmdLine cmd("Arithmetic expression evaluator", ' ', "1.0");
457
458 TCLAP::UnlabeledValueArg<string> exprArg("expression",
459 "Arithmetic expression to evaluate (use quotes)",
460 true, "", "expression");
461 cmd.add(exprArg);
462
463 cmd.parse(argc, argv);
464
465 string expr = exprArg.getValue();
466
467 cout << "Expression Evaluator" << endl;
468 cout << "====================" << endl;
469 cout << "Input: " << expr << endl;
470
471 // Create mutable copy for lexer
472 char* input = new char[expr.size() + 1];
473 strcpy(input, expr.c_str());
474
475 int result = eval(input);
476
477 cout << "Result: " << result << endl;
478
479 delete[] input;
480 }
481 catch (TCLAP::ArgException &e)
482 {
483 cerr << "Error: " << e.error() << " for arg " << e.argId() << endl;
484 return 1;
485 }
486
487 return 0;
488}
int main()
Token_Type
Definition btreepic.C:166
Stack implemented with simple dynamic array and with bounds verification.
T & top() const
Definition htlist.H:1683
T & push(const T &item)
Definition htlist.H:1523
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
char * str_to_token(const char *token_str, const size_t &len)
Convert token string to null-terminated string.
Definition evalExp.C:313
@ Value
Definition evalExp.C:272
@ Rpar
Definition evalExp.C:272
@ Error
Definition evalExp.C:272
@ End
Definition evalExp.C:272
@ Operator
Definition evalExp.C:272
@ Lpar
Definition evalExp.C:272
void apply(ArrayStack< int > &val_stack, ArrayStack< char > &op_stack)
Apply operator to top two values on stack.
Definition evalExp.C:345
Token_Type lexer(char *&str, size_t &len)
Lexer - extracts next token from input string.
Definition evalExp.C:281
unsigned precedence(const char &op)
Get operator precedence.
Definition evalExp.C:326
int eval(char *input)
Evaluate arithmetic expression.
Definition evalExp.C:390
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
void exit(const char *file, int line, const char *format,...)
Print a message and exit the program.
Definition ahDefs.C:132
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Stack implementations backed by dynamic or fixed arrays.