Home

Awesome

Tiny interpreter

Simple and fast command interpreter.
Library one header and source file.

Example:

stringstream ss;
ss << "$a = 5;"
      "$b = 2;"
      "while($a > 1){"
      "  $a -= 1;"
      "  $b = summ($b, $a);"
      "  if($a < 4){"
      "    break;"
      "  }"
      "}"
      "$b";
string res = ir.cmd(ss.str()); // 9

User functions outside the script

You can define any functions. Can be passed as parameters to other functions.
Simple addition

 ir.addFunction("summ", [](const vector<string>& args) ->string {
    int res = 0;
    for (auto& v : args) {
      if (isNumber(v)) res += stoi(v);
    }
    return to_string(res);
  });

Use in script

$c = 5; $d = $c + 5; summ($c, $d,  summ(6 + 5, 3));

User functions inside the script

You can define any functions in script

$a = 1; $b = 2; 
function myFunc{ $a += $b; };  // define
myFunc();                      // call                         

With params

function myFunc{ $0 += $1; };  // define
myFunc(2, 3);                  // call       

User operators

You can define any operators. Simple addition

 ir.addOperator("=", [](string& leftOpd, string& rightOpd) ->string {
    leftOpd = rightOpd;
    return leftOpd;
  }, 100);

 ir.addOperator("+=", [](string& leftOpd, string& rightOpd) ->string {
   if (isNumber(leftOpd) && isNumber(rightOpd)){
     leftOpd = to_string(stoi(leftOpd) + stoi(rightOpd));
     return leftOpd;
   }     
   else{
     leftOpd += rightOpd;
     return leftOpd;
   }
 }, 100);

Use in script

$c = 5;
$c += 5;

Variables

Must start with '$'

$a = 5;
$b = "string";

$a{12}   // initializer

Expressions

Start with any characters. Must end with ';'.
Parentheses increase the priority of the operation.
Can be passed as parameters to functions.

$a = 5; $b = 2; $c = $a * (2 + $b);
$d = summ($a, $b, $c + 3, 4);

Macros

Macro declaration with '#macro name {body}'

#macro myMac{ $c = 5; $d = $c + 5 + 6; };

Insert a macro with '#'

$c = 5; #myMac;

Insert a macro with params (index of param begin with 0)

#macro myMacr{ $a = $a + $0 + $0 + $1; };
$a = 5;  #myMacr(3,4); // result 15

Goto

Jump on label. Name of label must start with 'l_' and end with ':'

if ($a == 3){
  goto l_myLabel1;
}
l_myLabel1: $a = 4;

Control keywords

if(condition){body}Condition if expression in parentheses is nonzero
while(condition){body}Cycle if expression in parentheses is nonzero.
elseif(condition){body}If the previous condition is not met
else{body}If the previous condition is not met
break;Aborts the execution of the loop
continue;Continues the cycle

Structure from base lib

script = "e = Struct{ one : 5, two : 2}; e.one = summ(e.one, e.two); e.one";
res = ir.cmd(script); // 7

script = "$b = 12; e = Struct{ one : $b + 5, two : 2}; e.three = e.one + e.two + 3; e.three";
res = ir.cmd(script); // 22

Containers from base lib

script = "a = Vector{1,2,3}; a.push_back(4); a.push_back(5); while($v : a) print($v);";
res = ir.cmd(script); // 1 2 3 4 5

script = "b = Map{myKeyOne: myValueOne}; b.insert(myKeyTwo, myValueTwo); b.at(myKeyTwo)";
res = ir.cmd(script); // myValueTwo
VectorMap
push_back(value)insert(key, value)
pop_back()erase(key)
insert(index, value)size()
erase(index)empty()
size()clear()
empty()at(key)
clear()set(key)
at(index)
set(index)

Filesystem from base lib

script = "file1 = File{\"main.cpp\"}; file2 = File{\"mainCopy.txt\"};  \
          if (file1.exist()) { $data = file1.read(); file2.write($data); }";
res = ir.cmd(script);
FileDir
read()exist()
write(data)remove()
exist()
remove()

Types from base lib

script = "a: int = 123; type(a)";
res = ir.cmd(script); // int

script = "b: str = "abc"; type(b)";
res = ir.cmd(script); // str

Example of use


#include "../include/interpreter.h"
#include "../include/base_library/arithmetic_operations.h"
#include "../include/base_library/comparison_operations.h"
#include "../include/base_library/containers.h"
#include "../include/base_library/filesystem.h"
#include "../include/base_library/structure.h"
#include "../include/base_library/types.h"
#include <cctype>

using namespace std;

bool isNumber(const string& s) {
  for (auto c : s) {
    if (!std::isdigit(c)) {
      return false;
    }
  }
  return !s.empty();
}

int main(int argc, char* argv[])
{  
  Interpreter ir;

  InterpreterBaseLib::ArithmeticOperations ir_ao(ir);
  InterpreterBaseLib::ComparisonOperations ir_co(ir);
  InterpreterBaseLib::Types ir_tp(ir);
  InterpreterBaseLib::Container ir_bc(ir);
  InterpreterBaseLib::Filesystem ir_fs(ir);
  InterpreterBaseLib::Structure ir_st(ir);

  ir.addFunction("summ", [](const vector<string>& args) ->string {
    int res = 0;
    for (auto& v : args) {
      if (isNumber(v)) res += stoi(v);
    }
    return to_string(res);
  });

  ir.addFunction("print", [](const vector<string>& args) ->string {
    for (auto& v : args) {
      printf("%s ", v.c_str());
    }
    printf("\n");
    return "";
  });

  string script = "$a = 5; $b = 2; while ($a > 1){ $a = $a - 1; $b = summ($b, $a); if ($a < 4){ break;} } $b;";
  string res = ir.cmd(script); // 9
  
  script = "$a = 5; $b = 2; $c = summ($a, ($a + ($a * ($b + $a))), summ(5)); $c;";
  res = ir.cmd(script); // 50

  script = "a = Vector; a.push_back(1); a.push_back(2); a.push_back(3); a.size()";
  res = ir.cmd(script); // 3

  script = "b = Map; b.insert(myKeyOne, myValueOne); b.insert(myKeyTwo, myValueTwo); b.at(myKeyTwo)";
  res = ir.cmd(script); // myValueTwo

  script = "a = Vector; a.push_back(1); a.push_back(2); a.push_back(3); while($v : a) print($v);";
  res = ir.cmd(script); // 1 2 3
  
  script = "a = Vector{1 + 2, 2 + 3, 3 + 4}; while($v : a) print($v);";
  res = ir.cmd(script); // 3 5 7

  script = "$b = 12; c = Map{ one : $b + 5, two : 2}; while($v : c) print($v);";
  res = ir.cmd(script); // one 17 two 2

  script = "e = Struct{ one : 5, two : 2}; e.one = summ(e.one, e.two); e.one";
  res = ir.cmd(script); // 7

  script = "$b = 12; e = Struct{ one : $b + 5, two : 2}; e.three = e.one + e.two + 3; e.three";
  res = ir.cmd(script); // 22

  script = "file1 = File{\"main.cpp\"}; file2 = File{\"mainCopy.txt\"}; if (file1.exist()) { $data = file1.read(); file2.write($data); }";
  res = ir.cmd(script);
  
  script = "$a = 1; $b = 2; function myFunc{ $a += $b; }; myFunc()";
  res = ir.cmd(script); // 3
  
  script = "$a = 1; $b = 2; function myFunc{ $a += $b; function myFunc2{ $a += $b; }; myFunc2(); }; myFunc()";
  res = ir.cmd(script); // 5
  
  script = "$a = 0; function myFunc{ if ($0 > 1) $a = $0 * myFunc($0 - 1); else $a = 1; $a }; myFunc(5)";
  res = ir.cmd(script); // 120

  script = "function myFunc{ $0 += $1; }; myFunc(2, 3)";
  res = ir.cmd(script); // 5

  script = "b: str = \"abc\"; type(b)";
  res = ir.cmd(script); // str
  
  return 0;
}

Tests

License

Licensed under an [MIT-2.0]-license.