// File: /workspace/github_cpp_makefile_star2_O2/ArashPartow[P]exprtk-extras/exprtk_arithmetic_evaluator.cpp
// Function: void basic_arithmetic_parser_evaluator<double>()
void basic_arithmetic_parser_evaluator()
{
   typedef exprtk::symbol_table<T> symbol_table_t;
   typedef exprtk::expression<T>   expression_t;
   typedef exprtk::parser<T>       parser_t;

   const std::string arithmetic_parser_evaluator_program =
      " var curr_val := 0;                                "
      " var prev_val := 0;                                "
      " var result   := 0;                                "
      " var op       := '+';                              "
      "                                                   "
      " for (var i := 0; i < expression[]; i += 1)        "
      " {                                                 "
      "    var c := expression[i : i + 1];                "
      "                                                   "
      "    if (is_digit(c))                               "
      "    {                                              "
      "       curr_val := curr_val * 10 + to_num(c);      "
      "    };                                             "
      "                                                   "
      "    if (is_opr(c) or (i == expression[] - 1))      "
      "    {                                              "
      "       prev_val :=                                 "
      "          switch                                   "
      "          {                                        "
      "             case op == '+' :                      "
      "              ~{                                   "
      "                   result += prev_val;             "
      "                   curr_val;                       "
      "               };                                  "
      "                                                   "
      "             case op == '-' :                      "
      "              ~{                                   "
      "                  result += prev_val;              "
      "                  -curr_val;                       "
      "               };                                  "
      "                                                   "
      "             case op == '*' : prev_val * curr_val; "
      "             case op == '/' : prev_val / curr_val; "
      "          };                                       "
      "                                                   "
      "       curr_val := 0;                              "
      "       op       := c;                              "
      "    }                                              "
      " };                                                "
      "                                                   "
      " result += prev_val;                               "
      "                                                   "
      " println(result, ' = ', expression);               "
      "                                                   ";

   std::string arithmetic_expression;

   char_process<T,is_digit_func<T> >    isdigit;
   char_process<T,to_num_func<T> >      tonum;
   char_process<T,is_operator_func<T> > isopr;
   exprtk::rtl::io::println<T>          println;

   symbol_table_t symbol_table;
   symbol_table.add_stringvar("expression", arithmetic_expression);
   symbol_table.add_function ("println"   , println              );
   symbol_table.add_function ("is_digit"  , isdigit              );
   symbol_table.add_function ("is_opr"    , isopr                );
   symbol_table.add_function ("to_num"    , tonum                );

   expression_t expression;
   expression.register_symbol_table(symbol_table);

   parser_t parser;
   parser.compile(arithmetic_parser_evaluator_program, expression);

   /*
      Note: Expressions can be comprised of integers,
            basic arithmetic operators (+, -, *, /),
            and shall not contain parenthesises.
    */
   const std::vector<std::string> arithmetic_expressions =
   {
      "5 + 18 / 3",
      "4 + 3 * 15",
      "1 - 2 + 52 / 2 - 81 / 3",
   };

   for (const auto& expr : arithmetic_expressions)
   {
      arithmetic_expression = expr;
      expression.value();
   }
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0xc40, %rsp            # imm = 0xC40
leaq 0x12bdeb(%rip), %rsi    # 0x23c101
leaq 0x68(%rsp), %rdi
leaq 0x318(%rsp), %rdx
callq 0x1102c8
leaq 0x58(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0x118(%rsp), %rdi
callq 0x11085c
leaq 0xd0(%rsp), %rdi
callq 0x1108be
leaq 0x88(%rsp), %rdi
callq 0x110920
leaq 0x12c65f(%rip), %rsi    # 0x23c9c6
leaq 0x318(%rsp), %rdi
leaq 0x160(%rsp), %rdx
callq 0x1102c8
leaq 0x2b0(%rsp), %rdi
leaq 0x318(%rsp), %rsi
callq 0x110982
leaq 0x318(%rsp), %rdi
callq 0x10e5c8
movq %rsp, %rdi
pushq $0x1
popq %rsi
callq 0x110a14
leaq 0x12ee51(%rip), %rsi    # 0x23f201
leaq 0x318(%rsp), %rdi
leaq 0x160(%rsp), %rdx
callq 0x1102c8
movq %rsp, %rdi
leaq 0x318(%rsp), %rsi
leaq 0x48(%rsp), %rdx
xorl %ecx, %ecx
callq 0x110a38
leaq 0x318(%rsp), %rdi
callq 0x10e5c8
leaq 0x12c5dd(%rip), %rsi    # 0x23c9cd
leaq 0x318(%rsp), %rdi
leaq 0x160(%rsp), %rdx
callq 0x1102c8
movq %rsp, %rdi
leaq 0x318(%rsp), %rsi
leaq 0x2b0(%rsp), %rdx
callq 0x110aaa
leaq 0x318(%rsp), %rdi
callq 0x10e5c8
leaq 0x12c5a4(%rip), %rsi    # 0x23c9d5
leaq 0x318(%rsp), %rdi
leaq 0x160(%rsp), %rdx
callq 0x1102c8
movq %rsp, %rdi
leaq 0x318(%rsp), %rsi
leaq 0x118(%rsp), %rdx
callq 0x110aaa
leaq 0x318(%rsp), %rdi
callq 0x10e5c8
leaq 0x12c56c(%rip), %rsi    # 0x23c9de
leaq 0x318(%rsp), %rdi
leaq 0x160(%rsp), %rdx
callq 0x1102c8
movq %rsp, %rdi
leaq 0x318(%rsp), %rsi
leaq 0x88(%rsp), %rdx
callq 0x110aaa
leaq 0x318(%rsp), %rdi
callq 0x10e5c8
leaq 0x12c532(%rip), %rsi    # 0x23c9e5
leaq 0x318(%rsp), %rdi
leaq 0x160(%rsp), %rdx
callq 0x1102c8
movq %rsp, %rdi
leaq 0x318(%rsp), %rsi
leaq 0xd0(%rsp), %rdx
callq 0x110aaa
leaq 0x318(%rsp), %rdi
callq 0x10e5c8
leaq 0x28(%rsp), %rdi
callq 0x110b72
leaq 0x28(%rsp), %rdi
movq %rsp, %rsi
callq 0x110bd2
leaq 0x160(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x110c2e
leaq 0x318(%rsp), %rdi
leaq 0x160(%rsp), %rsi
callq 0x110d3e
leaq 0x160(%rsp), %rdi
callq 0x111356
leaq 0x318(%rsp), %rdi
leaq 0x68(%rsp), %rsi
leaq 0x28(%rsp), %rdx
callq 0x11139e
leaq 0x12c498(%rip), %rsi    # 0x23c9ec
leaq 0x160(%rsp), %r14
leaq 0xf(%rsp), %rdx
movq %r14, %rdi
callq 0x1102c8
leaq 0x180(%rsp), %r15
leaq 0x12c47f(%rip), %rsi    # 0x23c9f7
leaq 0xe(%rsp), %rdx
movq %r15, %rdi
callq 0x1102c8
leaq 0x1a0(%rsp), %r15
leaq 0x12c46e(%rip), %rsi    # 0x23ca02
leaq 0xd(%rsp), %rdx
movq %r15, %rdi
callq 0x1102c8
leaq 0x10(%rsp), %rdi
leaq 0x160(%rsp), %rsi
pushq $0x3
popq %rdx
leaq 0xc(%rsp), %rcx
callq 0x111820
pushq $0x40
popq %rbx
leaq (%rsp,%rbx), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x10e5c8
addq $-0x20, %rbx
cmpq $-0x20, %rbx
jne 0x1105be
movq 0x10(%rsp), %rbx
movq 0x18(%rsp), %r15
leaq 0x48(%rsp), %r14
cmpq %r15, %rbx
je 0x11060c
movq %r14, %rdi
movq %rbx, %rsi
callq 0x10e540
movq 0x28(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
addq $0x20, %rbx
jmp 0x1105e7
leaq 0x10(%rsp), %rdi
callq 0x11185a
leaq 0x318(%rsp), %rdi
callq 0x11187c
leaq 0x28(%rsp), %rdi
callq 0x1119b6
movq %rsp, %rdi
callq 0x1119cc
leaq 0x2b0(%rsp), %rdi
callq 0x111a0e
leaq 0x88(%rsp), %rdi
callq 0x111a24
leaq 0xd0(%rsp), %rdi
callq 0x111a24
leaq 0x118(%rsp), %rdi
callq 0x111a24
leaq 0x48(%rsp), %rdi
callq 0x10e5c8
leaq 0x68(%rsp), %rdi
callq 0x10e5c8
addq $0xc40, %rsp            # imm = 0xC40
popq %rbx
popq %r14
popq %r15
retq
movq %rax, %rbx
pushq $0x40
popq %r14
leaq (%rsp,%r14), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x10e5c8
addq $-0x20, %r14
cmpq $-0x20, %r14
jne 0x110691
jmp 0x11074c
jmp 0x1106b2
movq %rax, %rbx
addq $-0x20, %r15
movq %r15, %rdi
callq 0x10e5c8
cmpq %r14, %r15
jne 0x1106b5
jmp 0x11074c
jmp 0x1106cd
movq %rax, %rbx
jmp 0x11074c
movq %rax, %rbx
leaq 0x160(%rsp), %rdi
callq 0x111356
jmp 0x110759
jmp 0x1106e6
movq %rax, %rbx
jmp 0x110759
jmp 0x11070f
jmp 0x1106fd
jmp 0x11070f
jmp 0x1106fd
jmp 0x11070f
jmp 0x1106fd
jmp 0x11070f
jmp 0x1106fd
jmp 0x11070f
movq %rax, %rbx
leaq 0x318(%rsp), %rdi
callq 0x10e5c8
jmp 0x110763
movq %rax, %rbx
jmp 0x110763
movq %rax, %rbx
jmp 0x11076b
movq %rax, %rbx
leaq 0x318(%rsp), %rdi
callq 0x10e5c8
jmp 0x110778
movq %rax, %rbx
jmp 0x110778
movq %rax, %rbx
jmp 0x110785
movq %rax, %rbx
jmp 0x110792
movq %rax, %rbx
jmp 0x11079f
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x11185a
leaq 0x318(%rsp), %rdi
callq 0x11187c
leaq 0x28(%rsp), %rdi
callq 0x1119b6
movq %rsp, %rdi
callq 0x1119cc
leaq 0x2b0(%rsp), %rdi
callq 0x111a0e
leaq 0x88(%rsp), %rdi
callq 0x111a24
leaq 0xd0(%rsp), %rdi
callq 0x111a24
leaq 0x118(%rsp), %rdi
callq 0x111a24
leaq 0x48(%rsp), %rdi
callq 0x10e5c8
leaq 0x68(%rsp), %rdi
callq 0x10e5c8
movq %rbx, %rdi
callq 0x10e310