mirror of
https://github.com/louisrubet/rpn
synced 2025-01-01 18:20:06 +01:00
Add program type and eval command
This commit is contained in:
parent
9a77fb3f18
commit
00c01524b4
8 changed files with 145 additions and 42 deletions
59
src/parse.h
59
src/parse.h
|
@ -46,6 +46,41 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
tmp.clear();
|
||||
break;
|
||||
|
||||
//program
|
||||
case '<':
|
||||
//push prec entry if exists
|
||||
if (tmp.size()>0)
|
||||
{
|
||||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
}
|
||||
if (i<(entry.size()-1) && entry.at(i+1)=='<')
|
||||
{
|
||||
//get expression
|
||||
i+=2;
|
||||
tmp = "<<";
|
||||
while(i<entry.size())
|
||||
{
|
||||
if (i<(entry.size()-1) && entry.at(i) == '>' && entry.at(i+1) == '>')
|
||||
{
|
||||
tmp += ">>";
|
||||
i+=2;
|
||||
break;
|
||||
}
|
||||
else
|
||||
tmp+=entry.at(i);
|
||||
i++;
|
||||
}
|
||||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// reinject < which is not a program begin
|
||||
tmp = "<";
|
||||
}
|
||||
break;
|
||||
|
||||
//other
|
||||
default:
|
||||
if (entry.at(i)!=' ' && entry.at(i)!='\t')
|
||||
|
@ -68,7 +103,6 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
}
|
||||
|
||||
return entries.size()>0;
|
||||
}
|
||||
|
||||
|
@ -123,6 +157,23 @@ static bool get_string(const string& entry, object*& obj)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool get_program(const string& entry, object*& obj)
|
||||
{
|
||||
bool ret = false;
|
||||
int len = entry.size();
|
||||
if (len>=2 && entry[0]=='<' && entry[1]=='<')
|
||||
{
|
||||
int last;
|
||||
if (len>=4 && entry[len-1]=='>' && entry[len-2]=='>')
|
||||
last = len-4;
|
||||
else
|
||||
last = len-2;
|
||||
obj = new oprogram(entry.substr(2, last).c_str());
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool get_float(const string& entry, object*& obj)
|
||||
{
|
||||
stringstream token;
|
||||
|
@ -240,6 +291,12 @@ static bool _obj_from_string(const string& entry, object*& obj, unsigned int& ob
|
|||
obj_size = sizeof(ostring);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_program(entry, obj))
|
||||
{
|
||||
type = cmd_program;
|
||||
obj_size = sizeof(oprogram);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_keyword(entry, obj, obj_size, type))
|
||||
{
|
||||
ret = true;
|
||||
|
|
|
@ -20,9 +20,9 @@ void plus()
|
|||
else if (IS_ARG_TYPE(0, cmd_string))
|
||||
{
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_string);
|
||||
string& second = *((ostring*)_stack->back())->_name;
|
||||
string& second = *((ostring*)_stack->back())->_value;
|
||||
_stack->pop_back();
|
||||
*((ostring*)_stack->back())->_name += second;
|
||||
*((ostring*)_stack->back())->_value += second;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ int rpn_for(branch& myobj)
|
|||
|
||||
// store symbol with first value
|
||||
number num(myobj.farg1);
|
||||
_heap->add(*sym->_name, &num, sizeof(number), cmd_number);
|
||||
_heap->add(*sym->_value, &num, sizeof(number), cmd_number);
|
||||
|
||||
return myobj.arg1 + 1;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ int rpn_next(branch& myobj)
|
|||
int type;
|
||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||
// check symbol variable is a number, then increase
|
||||
if (_heap->get(*var->_name, obj, size, type) && (type == cmd_number))
|
||||
if (_heap->get(*var->_value, obj, size, type) && (type == cmd_number))
|
||||
((number*)obj)->_value = myobj.farg1;
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ int rpn_step(branch& myobj)
|
|||
int type;
|
||||
symbol* var = (symbol*)seq_obj(start_or_for->arg1);
|
||||
// check symbol variable is a number, then increase
|
||||
if (_heap->get(*var->_name, obj, size, type) && (type == cmd_number))
|
||||
if (_heap->get(*var->_value, obj, size, type) && (type == cmd_number))
|
||||
((number*)obj)->_value = myobj.farg1;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,10 @@ program::keyword_t program::_keywords[] =
|
|||
{ cmd_keyword, "purge", &program::purge, "delete a variable. ex: 'name' purge" },
|
||||
{ cmd_keyword, "vars", &program::vars, "list all variables" },
|
||||
|
||||
//PROGRAM
|
||||
{ cmd_undef, "", NULL, "\nPROGRAM"},
|
||||
{ cmd_keyword, "eval", &program::eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval" },
|
||||
|
||||
//TRIG
|
||||
{ cmd_undef, "", NULL, "\nTRIG"},
|
||||
{ cmd_keyword, "pi", &program::pi, "PI constant" },
|
||||
|
|
32
src/rpn-program.h
Normal file
32
src/rpn-program.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
void eval(void)
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
if (IS_ARG_TYPE(0, cmd_symbol))
|
||||
{
|
||||
// recall a variable
|
||||
void* obj;
|
||||
unsigned int size;
|
||||
int type;
|
||||
if (_heap->get(getn(), obj, size, type))
|
||||
_stack->push_back(obj, size, type);
|
||||
else
|
||||
ERR_CONTEXT(ret_unknown_variable);
|
||||
}
|
||||
else if (IS_ARG_TYPE(0, cmd_program))
|
||||
{
|
||||
string& entry = *((oprogram*)_stack->back())->_value;
|
||||
_stack->pop_back();
|
||||
|
||||
program prog;
|
||||
|
||||
// make program from string in stack level 1
|
||||
if (program::parse(entry, prog) == ret_ok)
|
||||
{
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
|
@ -31,7 +31,7 @@ void auto_rcl(symbol* symb)
|
|||
void* obj;
|
||||
unsigned int size;
|
||||
int type;
|
||||
if (_heap->get(*symb->_name, obj, size, type))
|
||||
if (_heap->get(*symb->_value, obj, size, type))
|
||||
_stack->push_back(obj, size, type);
|
||||
else
|
||||
_stack->push_back(symb, sizeof(symbol), cmd_symbol);
|
||||
|
|
|
@ -19,7 +19,7 @@ void strout()
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
string& entry = *((ostring*)_stack->back())->_name;
|
||||
string& entry = *((ostring*)_stack->back())->_value;
|
||||
_stack->pop_back();
|
||||
|
||||
program prog;
|
||||
|
|
78
src/rpn.cpp
78
src/rpn.cpp
|
@ -46,7 +46,7 @@ using namespace std;
|
|||
//TODO faut-il que ces variables soient globales ?
|
||||
static const char g_cursor[] = "> ";
|
||||
static const string g_show_stack_separator = ":\t";
|
||||
static const int g_max_commands = 100;
|
||||
static const int g_max_commands = 128;
|
||||
|
||||
//
|
||||
static int g_verbose = 0;
|
||||
|
@ -82,13 +82,14 @@ typedef enum {
|
|||
cmd_binary,/* binary (integer) value to put in stack */
|
||||
cmd_string,/* string value to put in stack */
|
||||
cmd_symbol,/* symbol value to put in stack */
|
||||
cmd_program,/* program */
|
||||
cmd_keyword,/* langage keyword */
|
||||
cmd_branch,/* langage branch keyword */
|
||||
cmd_max
|
||||
} cmd_type_t;
|
||||
|
||||
const char* cmd_type_string[cmd_max] = {
|
||||
"undef", "number", "binary", "symbol", "keyword", "keyword"
|
||||
"undef", "number", "binary", "symbol", "program", "keyword", "keyword"
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -185,46 +186,54 @@ binary::binary_enum binary::s_mode = binary::s_default_mode;
|
|||
class ostring : public object
|
||||
{
|
||||
public:
|
||||
ostring(string& name, cmd_type_t type = cmd_string) : object(type)
|
||||
ostring(string& value, cmd_type_t type = cmd_string) : object(type)
|
||||
{
|
||||
_name = new string(name);
|
||||
_value = new string(value);
|
||||
}
|
||||
ostring(const char* name, cmd_type_t type = cmd_string) : object(type)
|
||||
ostring(const char* value, cmd_type_t type = cmd_string) : object(type)
|
||||
{
|
||||
_name = new string(name);
|
||||
_value = new string(value);
|
||||
}
|
||||
virtual void show(ostream& stream = cout) { stream << "\"" << *_name << "\""; }
|
||||
string* _name;
|
||||
virtual void show(ostream& stream = cout) { stream << "\"" << *_value << "\""; }
|
||||
string* _value;
|
||||
};
|
||||
|
||||
class oprogram : public ostring
|
||||
{
|
||||
public:
|
||||
oprogram(string& value, cmd_type_t type = cmd_program) : ostring(value, type) { }
|
||||
oprogram(const char* value, cmd_type_t type = cmd_program) : ostring(value, type) { }
|
||||
virtual void show(ostream& stream = cout) { stream << "<< " << *_value << " >>"; }
|
||||
};
|
||||
|
||||
class symbol : public object
|
||||
{
|
||||
public:
|
||||
symbol(string& name, cmd_type_t type = cmd_symbol) : object(type), _auto_eval(false)
|
||||
symbol(string& value, cmd_type_t type = cmd_symbol) : object(type), _auto_eval(false)
|
||||
{
|
||||
_name = new string(name);
|
||||
_value = new string(value);
|
||||
}
|
||||
symbol(const char* name, cmd_type_t type = cmd_symbol) : object(type), _auto_eval(false)
|
||||
symbol(const char* value, cmd_type_t type = cmd_symbol) : object(type), _auto_eval(false)
|
||||
{
|
||||
_name = new string(name);
|
||||
_value = new string(value);
|
||||
}
|
||||
virtual void show(ostream& stream = cout) { stream << "'" << *_name << "'"; }
|
||||
string* _name;
|
||||
virtual void show(ostream& stream = cout) { stream << "'" << *_value << "'"; }
|
||||
string* _value;
|
||||
bool _auto_eval;
|
||||
};
|
||||
|
||||
class keyword : public symbol
|
||||
{
|
||||
public:
|
||||
keyword(program_fn_t fn, string& name, cmd_type_t type = cmd_keyword) : symbol(name, type) { _fn = fn; }
|
||||
keyword(program_fn_t fn, string& value, cmd_type_t type = cmd_keyword) : symbol(value, type) { _fn = fn; }
|
||||
program_fn_t _fn;
|
||||
virtual void show(ostream& stream = cout) { stream << *_name; }
|
||||
virtual void show(ostream& stream = cout) { stream << *_value; }
|
||||
};
|
||||
|
||||
class branch : public keyword
|
||||
{
|
||||
public:
|
||||
branch(branch_fn_t fn, string& name) : keyword(NULL, name, cmd_branch), arg1(-1), arg2(-1), arg3(-1), arg_bool(false)
|
||||
branch(branch_fn_t fn, string& value) : keyword(NULL, value, cmd_branch), arg1(-1), arg2(-1), arg3(-1), arg_bool(false)
|
||||
{
|
||||
_type = cmd_branch;
|
||||
_fn = fn;
|
||||
|
@ -281,15 +290,8 @@ public:
|
|||
cout << endl;
|
||||
}
|
||||
|
||||
// not a command, but a stack entry, manage it
|
||||
if ((type == cmd_number) || (type == cmd_binary) || (type == cmd_string))
|
||||
{
|
||||
stk.push_back(seq_obj(i), seq_len(i), type);
|
||||
i++;
|
||||
}
|
||||
|
||||
// could be an auto-evaluated symbol
|
||||
else if (type == cmd_symbol)
|
||||
if (type == cmd_symbol)
|
||||
{
|
||||
auto_rcl((symbol*)seq_obj(i));
|
||||
i++;
|
||||
|
@ -337,6 +339,13 @@ public:
|
|||
else
|
||||
i = tmp;
|
||||
}
|
||||
|
||||
// not a command, but a stack entry, manage it
|
||||
else
|
||||
{
|
||||
stk.push_back(seq_obj(i), seq_len(i), type);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -357,7 +366,7 @@ public:
|
|||
if (type == cmd_keyword)
|
||||
{
|
||||
keyword* k = (keyword*)seq_obj(i);
|
||||
if(k->_name->compare("end") == 0)
|
||||
if(k->_value->compare("end") == 0)
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
|
@ -387,14 +396,14 @@ public:
|
|||
else if (type == cmd_branch)
|
||||
{
|
||||
branch* k = (branch*)seq_obj(i);
|
||||
if (k->_name->compare("if") == 0)
|
||||
if (k->_value->compare("if") == 0)
|
||||
{
|
||||
if_layout_t layout;
|
||||
layout.index_if = i;
|
||||
vlayout.push_back(layout);
|
||||
layout_index++;
|
||||
}
|
||||
else if(k->_name->compare("then") == 0)
|
||||
else if(k->_value->compare("then") == 0)
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
|
@ -423,7 +432,7 @@ public:
|
|||
k->arg1 = next;
|
||||
k->arg3 = vlayout[layout_index].index_if;
|
||||
}
|
||||
else if(k->_name->compare("else") == 0)
|
||||
else if(k->_value->compare("else") == 0)
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
|
@ -459,16 +468,16 @@ public:
|
|||
k->arg3 = vlayout[layout_index].index_if;
|
||||
((branch*)seq_obj(vlayout[layout_index].index_then))->arg2 = next;// fill branch2 (if was false) of 'then'
|
||||
}
|
||||
else if(k->_name->compare("start") == 0)
|
||||
else if(k->_value->compare("start") == 0)
|
||||
{
|
||||
vstartindex.push_back(i);
|
||||
}
|
||||
else if(k->_name->compare("for") == 0)
|
||||
else if(k->_value->compare("for") == 0)
|
||||
{
|
||||
vstartindex.push_back(i);
|
||||
k->arg1 = i + 1;// arg1 points on symbol variable
|
||||
}
|
||||
else if(k->_name->compare("next") == 0)
|
||||
else if(k->_value->compare("next") == 0)
|
||||
{
|
||||
if (vstartindex.size() == 0)
|
||||
{
|
||||
|
@ -479,7 +488,7 @@ public:
|
|||
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'next' branch1 = 'start' index
|
||||
vstartindex.pop_back();
|
||||
}
|
||||
else if(k->_name->compare("step") == 0)
|
||||
else if(k->_value->compare("step") == 0)
|
||||
{
|
||||
if (vstartindex.size() == 0)
|
||||
{
|
||||
|
@ -620,7 +629,7 @@ private:
|
|||
string getn()
|
||||
{
|
||||
/* warning, caller must check object type before */
|
||||
string* a = ((symbol*)_stack->back())->_name;
|
||||
string* a = ((symbol*)_stack->back())->_value;
|
||||
_stack->pop_back();
|
||||
return *a;
|
||||
}
|
||||
|
@ -655,6 +664,7 @@ private:
|
|||
#include "rpn-string.h"
|
||||
#include "rpn-branch.h"
|
||||
#include "rpn-store.h"
|
||||
#include "rpn-program.h"
|
||||
#include "rpn-trig.h"
|
||||
#include "rpn-logs.h"
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue