Skip to content

Simple and fast tiny interpreter. Only one header and source file.

License

Notifications You must be signed in to change notification settings

Tyill/interpreter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

98 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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
Vector Map
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);
File Dir
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;
}

License

Licensed under an [MIT-2.0]-license.