diff --git a/src/parse.h b/src/parse.h index c1a00b4..6dfdc32 100644 --- a/src/parse.h +++ b/src/parse.h @@ -46,6 +46,41 @@ static bool _cut(const string& entry, vector& 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.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& 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; diff --git a/src/rpn-algebra.h b/src/rpn-algebra.h index 1bb3905..1a7870b 100644 --- a/src/rpn-algebra.h +++ b/src/rpn-algebra.h @@ -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; } } diff --git a/src/rpn-branch.h b/src/rpn-branch.h index 48f47df..54730c5 100644 --- a/src/rpn-branch.h +++ b/src/rpn-branch.h @@ -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; } diff --git a/src/rpn-cmd.h b/src/rpn-cmd.h index 1df715b..9120a40 100644 --- a/src/rpn-cmd.h +++ b/src/rpn-cmd.h @@ -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" }, diff --git a/src/rpn-program.h b/src/rpn-program.h new file mode 100644 index 0000000..1c9d0c6 --- /dev/null +++ b/src/rpn-program.h @@ -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); +} diff --git a/src/rpn-store.h b/src/rpn-store.h index 351d619..5c7f24d 100644 --- a/src/rpn-store.h +++ b/src/rpn-store.h @@ -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); diff --git a/src/rpn-string.h b/src/rpn-string.h index 87796cf..c514789 100644 --- a/src/rpn-string.h +++ b/src/rpn-string.h @@ -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; diff --git a/src/rpn.cpp b/src/rpn.cpp index fc647bd..d214b74 100644 --- a/src/rpn.cpp +++ b/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" };