mirror of
https://github.com/louisrubet/rpn
synced 2025-01-01 18:20:06 +01:00
No strings in objects
This commit is contained in:
parent
c8c38ac1cd
commit
e810a0fbe4
11 changed files with 343 additions and 164 deletions
221
src/parse.h
221
src/parse.h
|
@ -1,15 +1,42 @@
|
|||
static bool _cut(const string& entry, vector<string>& entries)
|
||||
// keywords declaration
|
||||
struct keyword_t
|
||||
{
|
||||
cmd_type_t type;
|
||||
char name[24];
|
||||
program_fn_t fn;
|
||||
string comment;
|
||||
};
|
||||
static keyword_t _keywords[g_max_commands];
|
||||
|
||||
static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type)
|
||||
{
|
||||
for(unsigned int i=0; (i<sizeof(_keywords)/sizeof(_keywords[0])) && (_keywords[i].type != cmd_max); i++)
|
||||
{
|
||||
if ((strnlen(_keywords[i].name, sizeof(_keywords[i].name))>0)
|
||||
&& (strncmp(fn_name, _keywords[i].name, sizeof(_keywords[i].name)) == 0))
|
||||
{
|
||||
fn = _keywords[i].fn;
|
||||
type = _keywords[i].type;
|
||||
return ret_ok;
|
||||
}
|
||||
}
|
||||
return ret_unknown_err;
|
||||
}
|
||||
|
||||
static bool _cut(const char* entry, vector<string>& entries)
|
||||
{
|
||||
string tmp;
|
||||
//TODO borner
|
||||
int len = strlen(entry);
|
||||
|
||||
for (int i=0; i<entry.size(); i++)
|
||||
for (int i=0; i < len; i++)
|
||||
{
|
||||
switch(entry.at(i))
|
||||
switch(entry[i])
|
||||
{
|
||||
//symbol
|
||||
case '\'':
|
||||
//push prec entry if exists
|
||||
if (tmp.size()>0)
|
||||
if (tmp.size() > 0)
|
||||
{
|
||||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
|
@ -17,10 +44,10 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
//get symbol
|
||||
tmp='\'';
|
||||
i++;
|
||||
while((i<entry.size()) && (isalnum(entry.at(i)) || entry.at(i)=='_'))
|
||||
tmp+=entry.at(i++);
|
||||
if ((i<entry.size()) && entry.at(i)=='\'')
|
||||
tmp+='\'';
|
||||
while((i < len) && (isalnum(entry[i]) || entry[i]=='_'))
|
||||
tmp += entry[i++];
|
||||
if ((i < len) && entry[i] == '\'')
|
||||
tmp += '\'';
|
||||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
break;
|
||||
|
@ -28,7 +55,7 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
//string
|
||||
case '"':
|
||||
//push prec entry if exists
|
||||
if (tmp.size()>0)
|
||||
if (tmp.size() > 0)
|
||||
{
|
||||
entries.push_back(tmp);
|
||||
tmp.clear();
|
||||
|
@ -36,10 +63,10 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
//get expression
|
||||
tmp='"';
|
||||
i++;
|
||||
while(i<entry.size() && entry.at(i)>=' ')
|
||||
while(i < len && entry[i] >= ' ')
|
||||
{
|
||||
tmp+=entry.at(i);
|
||||
if (entry.at(i++) == '"')
|
||||
tmp += entry[i];
|
||||
if (entry[i++] == '"')
|
||||
break;
|
||||
}
|
||||
entries.push_back(tmp);
|
||||
|
@ -55,35 +82,37 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
tmp.clear();
|
||||
}
|
||||
|
||||
if (entry.substr(i, 2) == "<<")
|
||||
if (strncmp(&entry[i], "<<", 2) == 0)
|
||||
{
|
||||
int up = 1;
|
||||
|
||||
// found a program begin
|
||||
i+=2;
|
||||
tmp="<< ";
|
||||
i += 2;
|
||||
tmp = "<< ";
|
||||
|
||||
// trim leading spaces
|
||||
while (i<entry.size() && (entry.at(i)==' ' || entry.at(i)=='\t'))
|
||||
while (i < len && (entry[i]==' ' || entry[i]=='\t'))
|
||||
i++;
|
||||
|
||||
while(i<entry.size())
|
||||
while(i < len)
|
||||
{
|
||||
if (entry.substr(i, 2) == "<<")
|
||||
if (strncmp(&entry[i], "<<", 2) == 0)
|
||||
{
|
||||
up++;
|
||||
i+=2;
|
||||
tmp+=" << ";
|
||||
i += 2;
|
||||
tmp += " << ";
|
||||
// trim leading spaces
|
||||
while (i<entry.size() && (entry.at(i)==' ' || entry.at(i)=='\t'))
|
||||
while (i < len && (entry[i] == ' ' || entry[i] == '\t'))
|
||||
i++;
|
||||
}
|
||||
else if (entry.substr(i, 2) == ">>")
|
||||
else if (strncmp(&entry[i], ">>", 2) == 0)
|
||||
{
|
||||
up--;
|
||||
i+=2;
|
||||
tmp+=" >>";
|
||||
i += 2;
|
||||
tmp += " >>";
|
||||
|
||||
// trim trailing spaces
|
||||
while (i<entry.size() && (entry.at(i)==' ' || entry.at(i)=='\t'))
|
||||
while (i < len && (entry[i] == ' ' || entry[i] == '\t'))
|
||||
i++;
|
||||
// found end
|
||||
if (up == 0)
|
||||
|
@ -91,7 +120,7 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
}
|
||||
else
|
||||
{
|
||||
tmp+=entry[i];
|
||||
tmp += entry[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -114,9 +143,9 @@ static bool _cut(const string& entry, vector<string>& entries)
|
|||
|
||||
//other
|
||||
default:
|
||||
if (entry.at(i)!=' ' && entry.at(i)!='\t')
|
||||
if (entry[i] != ' ' && entry[i] != '\t')
|
||||
{
|
||||
tmp+=entry.at(i);
|
||||
tmp += entry[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -147,14 +176,18 @@ static bool get_keyword(const string& entry, object*& obj, unsigned int& obj_siz
|
|||
{
|
||||
if (type == cmd_keyword)
|
||||
{
|
||||
obj = new keyword(fn, (string&)entry);
|
||||
obj_size = sizeof(keyword);
|
||||
// allocate keyword object
|
||||
obj_size = sizeof(keyword) + entry.size();
|
||||
obj = (object*)malloc(obj_size);
|
||||
((keyword*)obj)->set(fn, entry.c_str(), entry.size());
|
||||
ret = true;
|
||||
}
|
||||
else if (type == cmd_branch)
|
||||
{
|
||||
obj = new branch((branch_fn_t)fn, (string&)entry);
|
||||
obj_size = sizeof(branch);
|
||||
// allocate branch object
|
||||
obj_size = sizeof(branch) + entry.size();
|
||||
obj = (object*)malloc(obj_size);
|
||||
((branch*)obj)->set((branch_fn_t)fn, entry.c_str(), entry.size());
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -162,44 +195,79 @@ static bool get_keyword(const string& entry, object*& obj, unsigned int& obj_siz
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool get_symbol(const string& entry, object*& obj)
|
||||
static bool get_symbol(const string& entry, object*& obj, unsigned int& obj_len)
|
||||
{
|
||||
bool ret = false;
|
||||
int len = entry.size();
|
||||
if (len>1 && entry[0]=='\'')
|
||||
int entry_len = entry.size();
|
||||
if (entry_len>1 && entry[0]=='\'')
|
||||
{
|
||||
int last = entry[len-1]=='\''?(len-2):(len-1);
|
||||
obj = new symbol(entry.substr(1, last).c_str());
|
||||
int naked_entry_len;
|
||||
|
||||
// entry length without prefix / postfix
|
||||
naked_entry_len = entry[entry_len-1]=='\''?(entry_len-3):(entry_len-2);
|
||||
|
||||
// total object length
|
||||
obj_len = sizeof(symbol) + naked_entry_len;
|
||||
|
||||
// allocate object
|
||||
obj = (object*)malloc(obj_len);
|
||||
|
||||
// set it
|
||||
((symbol*)obj)->set(&entry[1], naked_entry_len);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool get_string(const string& entry, object*& obj)
|
||||
static bool get_string(const string& entry, object*& obj, unsigned int& obj_len)
|
||||
{
|
||||
bool ret = false;
|
||||
int len = entry.size();
|
||||
if (len>1 && entry[0]=='\"')
|
||||
int entry_len = entry.size();
|
||||
if (entry_len>1 && entry[0]=='"')
|
||||
{
|
||||
int last = entry[len-1]=='\"'?(len-2):(len-1);
|
||||
obj = new ostring(entry.substr(1, last).c_str());
|
||||
int naked_entry_len;
|
||||
|
||||
// entry length without prefix / postfix
|
||||
naked_entry_len = entry[entry_len-1]=='"'?(entry_len-3):(entry_len-2);
|
||||
|
||||
// total object length
|
||||
obj_len = sizeof(ostring) + naked_entry_len;
|
||||
|
||||
// allocate object
|
||||
obj = (object*)malloc(obj_len);
|
||||
|
||||
// set it
|
||||
((ostring*)obj)->set(&entry[1], naked_entry_len);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool get_program(const string& entry, object*& obj)
|
||||
static bool get_program(const string& entry, object*& obj, unsigned int& obj_len)
|
||||
{
|
||||
bool ret = false;
|
||||
int len = entry.size();
|
||||
if (len>=2 && entry[0]=='<' && entry[1]=='<')
|
||||
int entry_len = entry.size();
|
||||
if (entry_len>=2 && entry[0]=='<' && entry[1]=='<')
|
||||
{
|
||||
int last;
|
||||
if (len>=4 && entry[len-1]=='>' && entry[len-2]=='>')
|
||||
last = len-4;
|
||||
int naked_entry_len;
|
||||
|
||||
// entry length without prefix / postfix
|
||||
if (entry_len>=4 && entry[entry_len-1]=='>' && entry[entry_len-2]=='>')
|
||||
naked_entry_len = entry_len-4;
|
||||
else
|
||||
last = len-2;
|
||||
obj = new oprogram(entry.substr(2, last).c_str());
|
||||
naked_entry_len = entry_len-2;
|
||||
|
||||
// total object length
|
||||
obj_len = sizeof(oprogram) + naked_entry_len;
|
||||
|
||||
// allocate object
|
||||
obj = (object*)malloc(obj_len);
|
||||
|
||||
// set it
|
||||
((oprogram*)obj)->set(&entry[2], naked_entry_len);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
|
@ -208,15 +276,17 @@ static bool get_program(const string& entry, object*& obj)
|
|||
// care: not threadsafe
|
||||
static bool get_float(const string& entry, object*& obj)
|
||||
{
|
||||
static number new_number(0);
|
||||
static number new_number;
|
||||
floating_t val;
|
||||
stringstream token;
|
||||
bool ret = false;
|
||||
|
||||
token<<entry;
|
||||
token>>new_number._value;
|
||||
token>>val;
|
||||
|
||||
if ( (!token.fail()) && (!token.bad()) )
|
||||
{
|
||||
new_number.set(val);
|
||||
obj = &new_number;
|
||||
ret = true;
|
||||
}
|
||||
|
@ -227,9 +297,10 @@ static bool get_float(const string& entry, object*& obj)
|
|||
// care: not threadsafe
|
||||
static bool get_binary(const string& entry, object*& obj)
|
||||
{
|
||||
static binary new_binary(0);
|
||||
static binary new_binary;
|
||||
integer_t val;
|
||||
bool ret = false;
|
||||
|
||||
if ((entry.size() >= 2) && (entry[0] == '#'))
|
||||
{
|
||||
stringstream token;
|
||||
|
@ -255,9 +326,10 @@ static bool get_binary(const string& entry, object*& obj)
|
|||
break;
|
||||
}
|
||||
|
||||
token>>new_binary._value;
|
||||
token>>val;
|
||||
if(syntax && !token.fail())
|
||||
{
|
||||
new_binary.set(val);
|
||||
obj = &new_binary;
|
||||
ret = true;
|
||||
}
|
||||
|
@ -266,8 +338,10 @@ static bool get_binary(const string& entry, object*& obj)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// care: not threadsafe
|
||||
static bool get_binary_bin(const string& entry, object*& obj)
|
||||
{
|
||||
static binary new_binary;
|
||||
integer_t val;
|
||||
int len = entry.size();
|
||||
bool ret = false;
|
||||
|
@ -284,7 +358,8 @@ static bool get_binary_bin(const string& entry, object*& obj)
|
|||
exponent/=2;
|
||||
}
|
||||
}
|
||||
obj = new binary(val);
|
||||
new_binary.set(val);
|
||||
obj = &new_binary;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
@ -313,19 +388,17 @@ static bool _obj_from_string(const string& entry, object*& obj, unsigned int& ob
|
|||
obj_size = sizeof(binary);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_symbol(entry, obj))
|
||||
else if (get_symbol(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_symbol;
|
||||
obj_size = sizeof(symbol);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_string(entry, obj))
|
||||
else if (get_string(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_string;
|
||||
obj_size = sizeof(ostring);
|
||||
ret = true;
|
||||
}
|
||||
else if (get_program(entry, obj))
|
||||
else if (get_program(entry, obj, obj_size))
|
||||
{
|
||||
type = cmd_program;
|
||||
obj_size = sizeof(oprogram);
|
||||
|
@ -338,9 +411,8 @@ static bool _obj_from_string(const string& entry, object*& obj, unsigned int& ob
|
|||
else
|
||||
{
|
||||
// nothing, considered as an auto-evaluated symbol
|
||||
obj = new symbol((string&)entry);
|
||||
(void)get_symbol(entry, obj, obj_size);
|
||||
((symbol*)obj)->_auto_eval = true;
|
||||
obj_size = sizeof(symbol);
|
||||
type = cmd_symbol;
|
||||
ret = true;
|
||||
}
|
||||
|
@ -348,6 +420,22 @@ static bool _obj_from_string(const string& entry, object*& obj, unsigned int& ob
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void _delete_obj_from_string(object* obj)
|
||||
{
|
||||
if (obj != NULL)
|
||||
{
|
||||
switch (obj->_type)
|
||||
{
|
||||
case cmd_number:
|
||||
case cmd_binary:
|
||||
break;
|
||||
default:
|
||||
free(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char* entry_completion_generator(const char* text, int state)
|
||||
{
|
||||
static int list_index, len, too_far;
|
||||
|
@ -389,7 +477,7 @@ static char* entry_completion_dupstr(char* s)
|
|||
return r;
|
||||
}
|
||||
|
||||
static ret_value parse(const string& entry, program& prog)
|
||||
static ret_value parse(const char* entry, program& prog)
|
||||
{
|
||||
vector<string> entries;
|
||||
ret_value ret = ret_ok;
|
||||
|
@ -406,6 +494,7 @@ static ret_value parse(const string& entry, program& prog)
|
|||
if(_obj_from_string((*it), obj, obj_size, type))
|
||||
{
|
||||
prog.push_back(obj, obj_size, type);
|
||||
_delete_obj_from_string(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -420,7 +509,7 @@ static ret_value parse(const string& entry, program& prog)
|
|||
// interactive entry and decoding
|
||||
static ret_value entry(program& prog)
|
||||
{
|
||||
char *buf;
|
||||
char* buf;
|
||||
ret_value ret;
|
||||
|
||||
// declare completion fn (bound to '\t' by default)
|
||||
|
@ -430,10 +519,8 @@ static ret_value entry(program& prog)
|
|||
buf = readline(prompt);
|
||||
if (buf != NULL)
|
||||
{
|
||||
string entry(buf);
|
||||
|
||||
// parse it
|
||||
ret = parse(entry, prog);
|
||||
ret = parse(buf, prog);
|
||||
|
||||
// keep history
|
||||
if (buf[0]!=0)
|
||||
|
|
|
@ -16,7 +16,9 @@ void plus()
|
|||
//TODO really too slow
|
||||
putb(getb() + getb());
|
||||
}
|
||||
// string
|
||||
//TODO
|
||||
#if 0
|
||||
// string
|
||||
else if (IS_ARG_TYPE(0, cmd_string))
|
||||
{
|
||||
ARG_MUST_BE_OF_TYPE(1, cmd_string);
|
||||
|
@ -24,6 +26,7 @@ void plus()
|
|||
_stack->pop_back();
|
||||
*((ostring*)_stack->back())->_value += second;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ERR_CONTEXT(ret_bad_operand_type);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ void rtob()
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
||||
|
||||
binary bin((integer_t)getf());
|
||||
binary bin;
|
||||
bin.set(((integer_t)getf()));
|
||||
_stack->push_back(&bin, sizeof(binary), cmd_binary);
|
||||
|
||||
}
|
||||
|
|
|
@ -70,8 +70,9 @@ int rpn_for(branch& myobj)
|
|||
myobj.farg1 = getf();
|
||||
|
||||
// store symbol with first value
|
||||
number num(myobj.farg1);
|
||||
_heap->add(*sym->_value, &num, sizeof(number), cmd_number);
|
||||
number num;
|
||||
num.set(myobj.farg1);
|
||||
_heap->add(string(sym->_value), &num, sizeof(number), cmd_number);
|
||||
|
||||
return myobj.arg1 + 1;
|
||||
}
|
||||
|
@ -98,7 +99,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->_value, obj, size, type) && (type == cmd_number))
|
||||
if (_heap->get(string(var->_value), obj, size, type) && (type == cmd_number))
|
||||
((number*)obj)->_value = myobj.farg1;
|
||||
}
|
||||
|
||||
|
@ -143,7 +144,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->_value, obj, size, type) && (type == cmd_number))
|
||||
if (_heap->get(string(var->_value), obj, size, type) && (type == cmd_number))
|
||||
((number*)obj)->_value = myobj.farg1;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ void eval(void)
|
|||
void* obj;
|
||||
unsigned int size;
|
||||
int type;
|
||||
string& variable = *((symbol*)_stack->back())->_value;
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
if (_heap->get(variable, obj, size, type))
|
||||
{
|
||||
_stack->pop_back();
|
||||
|
@ -20,13 +20,13 @@ void eval(void)
|
|||
else if (IS_ARG_TYPE(0, cmd_program))
|
||||
{
|
||||
// eval a program
|
||||
string& entry = *((oprogram*)_stack->back())->_value;
|
||||
string entry(((oprogram*)_stack->back())->_value);
|
||||
_stack->pop_back();
|
||||
|
||||
program prog;
|
||||
|
||||
// make program from entry
|
||||
if (program::parse(entry, prog) == ret_ok)
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||
{
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
|
@ -100,16 +100,16 @@ int inprog(branch& myobj)
|
|||
// load variables
|
||||
for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--)
|
||||
{
|
||||
_heap->add(*((symbol*)seq_obj(i))->_value, _stack->get_obj(0), _stack->get_len(0), _stack->get_type(0));
|
||||
_heap->add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0), _stack->get_len(0), _stack->get_type(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
|
||||
// run the program
|
||||
string& entry = *((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value;
|
||||
string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value);
|
||||
program prog;
|
||||
|
||||
// make the program from entry
|
||||
if (program::parse(entry, prog) == ret_ok)
|
||||
if (program::parse(entry.c_str(), prog) == ret_ok)
|
||||
{
|
||||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
|
|
|
@ -76,6 +76,7 @@ void rot(void)
|
|||
|
||||
void depth(void)
|
||||
{
|
||||
number num((floating_t)_stack->size());
|
||||
number num;
|
||||
num.set((floating_t)_stack->size());
|
||||
_stack->push_back(&num, sizeof(number), cmd_number);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ void sto(void)
|
|||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
string name = getn();
|
||||
string name(getn());
|
||||
_heap->add(name, _stack->get_obj(0), _stack->get_len(0), _stack->get_type(0));
|
||||
_stack->pop_back();
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ void rcl(void)
|
|||
void* obj;
|
||||
unsigned int size;
|
||||
int type;
|
||||
string& variable = *((symbol*)_stack->back())->_value;
|
||||
string variable(((symbol*)_stack->back())->_value);
|
||||
if (_heap->get(variable, obj, size, type))
|
||||
{
|
||||
_stack->pop_back();
|
||||
|
@ -36,7 +36,7 @@ void auto_rcl(symbol* symb)
|
|||
void* obj;
|
||||
unsigned int size;
|
||||
int type;
|
||||
if (_heap->get(*symb->_value, obj, size, type))
|
||||
if (_heap->get(string(symb->_value), obj, size, type))
|
||||
_stack->push_back(obj, size, type);
|
||||
else
|
||||
_stack->push_back(symb, sizeof(symbol), cmd_symbol);
|
||||
|
@ -50,7 +50,7 @@ void purge(void)
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
||||
|
||||
if (!_heap->erase(getn()))
|
||||
if (!_heap->erase(string(getn())))
|
||||
ERR_CONTEXT(ret_unknown_variable);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ void instr()
|
|||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
//TODO
|
||||
#if 0
|
||||
// stringify only if not already a string
|
||||
if (_stack->get_type(0) != cmd_string)
|
||||
{
|
||||
|
@ -12,11 +14,14 @@ void instr()
|
|||
ostring* str = new ostring(out.str().c_str());
|
||||
_stack->push_back(str, sizeof(ostring), cmd_string);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void strout()
|
||||
{
|
||||
MIN_ARGUMENTS(1);
|
||||
//TODO
|
||||
#if 0
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
||||
|
||||
string& entry = *((ostring*)_stack->back())->_value;
|
||||
|
@ -30,4 +35,5 @@ void strout()
|
|||
// run it
|
||||
prog.run(*_stack, *_heap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ void program::test()
|
|||
{
|
||||
// parse entry and run line
|
||||
program prog;
|
||||
ret = program::parse(entry, prog);
|
||||
ret = program::parse(entry.c_str(), prog);
|
||||
if (ret == ret_ok)
|
||||
{
|
||||
// run it
|
||||
|
|
|
@ -63,11 +63,14 @@ void eq(void)
|
|||
putf(getf() == first);
|
||||
}
|
||||
break;
|
||||
//TODO
|
||||
#if 0
|
||||
case cmd_symbol:
|
||||
{
|
||||
string first = getn();
|
||||
putf(getn() == first);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
_stack->pop_back();
|
||||
|
|
233
src/rpn.cpp
233
src/rpn.cpp
|
@ -106,22 +106,27 @@ typedef union
|
|||
typedef int (program::*branch_fn_t)(branch&);
|
||||
|
||||
//
|
||||
class object
|
||||
struct object
|
||||
{
|
||||
public:
|
||||
cmd_type_t _type;// object type
|
||||
object(cmd_type_t type = cmd_undef):_type(type) { }
|
||||
// object type
|
||||
cmd_type_t _type;
|
||||
|
||||
//
|
||||
void show(ostream& stream = cout);
|
||||
};
|
||||
|
||||
class number : public object
|
||||
struct number : public object
|
||||
{
|
||||
public:
|
||||
number(floating_t value) : object(cmd_number) { _value = value; }
|
||||
floating_t _value;
|
||||
|
||||
// representation mode
|
||||
//
|
||||
void set(floating_t value)
|
||||
{
|
||||
_type = cmd_number;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
// representation mode
|
||||
typedef enum {
|
||||
std,
|
||||
fix,
|
||||
|
@ -139,12 +144,17 @@ number::mode_enum number::s_mode = number::s_default_mode;
|
|||
int number::s_default_precision = 20;
|
||||
int number::s_current_precision = number::s_default_precision;
|
||||
|
||||
class binary : public object
|
||||
struct binary : public object
|
||||
{
|
||||
public:
|
||||
binary(integer_t value) : object(cmd_binary) { _value = value; }
|
||||
integer_t _value;
|
||||
|
||||
//
|
||||
void set(integer_t value)
|
||||
{
|
||||
_type = cmd_binary;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
// representation mode
|
||||
typedef enum {
|
||||
dec,
|
||||
|
@ -158,12 +168,12 @@ public:
|
|||
binary::binary_enum binary::s_default_mode = binary::dec;
|
||||
binary::binary_enum binary::s_mode = binary::s_default_mode;
|
||||
|
||||
class ostring : public object
|
||||
struct ostring : public object
|
||||
{
|
||||
public:
|
||||
ostring(cmd_type_t type = cmd_string) : object(type), len(0) { }
|
||||
//
|
||||
void set(const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_string;
|
||||
if (value != NULL)
|
||||
{
|
||||
(void)memcpy(_value, value, len);
|
||||
|
@ -174,44 +184,109 @@ public:
|
|||
len = 0;
|
||||
}
|
||||
|
||||
//
|
||||
unsigned int _len;
|
||||
char _value[];
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
class oprogram : public ostring
|
||||
struct oprogram : public object
|
||||
{
|
||||
public:
|
||||
oprogram(cmd_type_t type = cmd_program) : ostring(type) { }
|
||||
//
|
||||
void set(const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_program;
|
||||
if (value != NULL)
|
||||
{
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
|
||||
//
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
class symbol : public ostring
|
||||
struct symbol : public object
|
||||
{
|
||||
public:
|
||||
symbol(cmd_type_t type = cmd_symbol) : ostring(type), _auto_eval(false) { }
|
||||
bool _auto_eval;
|
||||
//
|
||||
void set(const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_symbol;
|
||||
_auto_eval = false;
|
||||
if (value != NULL)
|
||||
{
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
|
||||
//
|
||||
bool _auto_eval;
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
class keyword : public symbol
|
||||
struct keyword : public object
|
||||
{
|
||||
public:
|
||||
keyword(program_fn_t fn, cmd_type_t type = cmd_keyword) : symbol(type) { _fn = fn; }
|
||||
program_fn_t _fn;
|
||||
//
|
||||
void set(program_fn_t fn, const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_keyword;
|
||||
_fn = fn;
|
||||
if (value != NULL)
|
||||
{
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
|
||||
//
|
||||
program_fn_t _fn;
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
class branch : public keyword
|
||||
struct branch : public object
|
||||
{
|
||||
public:
|
||||
branch(branch_fn_t fn) : keyword(NULL, cmd_branch), arg1(-1), arg2(-1), arg3(-1), arg_bool(false)
|
||||
{
|
||||
_type = cmd_branch;
|
||||
_fn = fn;
|
||||
}
|
||||
// branch function
|
||||
branch_fn_t _fn;
|
||||
// args used by cmd_branch cmds
|
||||
int arg1, arg2, arg3;
|
||||
floating_t farg1, farg2;
|
||||
bool arg_bool;
|
||||
//
|
||||
void set(branch_fn_t fn, const char* value, unsigned int len)
|
||||
{
|
||||
_type = cmd_branch;
|
||||
_fn = fn;
|
||||
arg1 = -1;
|
||||
arg2 = -1;
|
||||
arg3 = -1;
|
||||
farg1 = 0;
|
||||
farg2 = 0;
|
||||
arg_bool = 0;
|
||||
if (value != NULL)
|
||||
{
|
||||
(void)memcpy(_value, value, len);
|
||||
_value[len] = 0;
|
||||
_len = len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
|
||||
// branch function
|
||||
branch_fn_t _fn;
|
||||
// args used by cmd_branch cmds
|
||||
int arg1, arg2, arg3;
|
||||
floating_t farg1, farg2;
|
||||
bool arg_bool;
|
||||
unsigned int _len;
|
||||
char _value[0];
|
||||
};
|
||||
|
||||
void object::show(ostream& stream)
|
||||
|
@ -368,7 +443,23 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret_value preprocess(void)
|
||||
bool compare_keyword(keyword* k, const char* str_to_compare, int len)
|
||||
{
|
||||
if (k->_len >= len)
|
||||
return strncmp(k->_value, str_to_compare, len) == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool compare_branch(branch* b, const char* str_to_compare, int len)
|
||||
{
|
||||
if (b->_len >= len)
|
||||
return strncmp(b->_value, str_to_compare, len) == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
ret_value preprocess(void)
|
||||
{
|
||||
// for if-then-else-end
|
||||
vector<struct if_layout_t> vlayout;
|
||||
|
@ -384,7 +475,7 @@ public:
|
|||
if (type == cmd_keyword)
|
||||
{
|
||||
keyword* k = (keyword*)seq_obj(i);
|
||||
if (strncmp(k->_value, "end", 3) == 0)
|
||||
if (compare_keyword(k, "end", 3))
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
|
@ -414,14 +505,14 @@ public:
|
|||
else if (type == cmd_branch)
|
||||
{
|
||||
branch* k = (branch*)seq_obj(i);
|
||||
if (strncmp(k->_value, "if", 2) == 0)
|
||||
if (compare_branch(k, "if", 2))
|
||||
{
|
||||
if_layout_t layout;
|
||||
layout.index_if = i;
|
||||
vlayout.push_back(layout);
|
||||
layout_index++;
|
||||
}
|
||||
else if (strncmp(k->_value, "then", 4) == 0)
|
||||
else if (compare_branch(k, "then", 4))
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
|
@ -450,7 +541,7 @@ public:
|
|||
k->arg1 = next;
|
||||
k->arg3 = vlayout[layout_index].index_if;
|
||||
}
|
||||
else if (strncmp(k->_value, "else", 4) == 0)
|
||||
else if (compare_branch(k, "else", 4))
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
|
@ -486,16 +577,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 (strncmp(k->_value, "start", 5) == 0)
|
||||
else if (compare_branch(k, "start", 5))
|
||||
{
|
||||
vstartindex.push_back(i);
|
||||
}
|
||||
else if (strncmp(k->_value, "for", 3) == 0)
|
||||
else if (compare_branch(k, "for", 3))
|
||||
{
|
||||
vstartindex.push_back(i);
|
||||
k->arg1 = i + 1;// arg1 points on symbol variable
|
||||
}
|
||||
else if(strncmp(k->_value, "next", 4) == 0)
|
||||
else if(compare_branch(k, "next", 4))
|
||||
{
|
||||
if (vstartindex.size() == 0)
|
||||
{
|
||||
|
@ -506,7 +597,7 @@ public:
|
|||
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'next' branch1 = 'start' index
|
||||
vstartindex.pop_back();
|
||||
}
|
||||
else if (strncmp(k->_value, "step", 4) == 0)
|
||||
else if (compare_branch(k, "step", 4))
|
||||
{
|
||||
if (vstartindex.size() == 0)
|
||||
{
|
||||
|
@ -517,7 +608,7 @@ public:
|
|||
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'step' branch1 = 'start' index
|
||||
vstartindex.pop_back();
|
||||
}
|
||||
else if (strncmp(k->_value, "->", 2) == 0)
|
||||
else if (compare_branch(k, "->", 2))
|
||||
{
|
||||
k->arg1 = i;// arg1 is '->' command index in program
|
||||
}
|
||||
|
@ -562,31 +653,6 @@ public:
|
|||
cerr<<"syntax error: "<<context<<endl;
|
||||
}
|
||||
|
||||
// keywords declaration
|
||||
struct keyword_t
|
||||
{
|
||||
cmd_type_t type;
|
||||
char name[24];
|
||||
program_fn_t fn;
|
||||
string comment;
|
||||
};
|
||||
static keyword_t _keywords[g_max_commands];
|
||||
|
||||
static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type)
|
||||
{
|
||||
for(unsigned int i=0; (i<sizeof(_keywords)/sizeof(_keywords[0])) && (_keywords[i].type != cmd_max); i++)
|
||||
{
|
||||
if ((strnlen(_keywords[i].name, sizeof(_keywords[i].name))>0)
|
||||
&& (strncmp(fn_name, _keywords[i].name, sizeof(_keywords[i].name)) == 0))
|
||||
{
|
||||
fn = _keywords[i].fn;
|
||||
type = _keywords[i].type;
|
||||
return ret_ok;
|
||||
}
|
||||
}
|
||||
return ret_unknown_err;
|
||||
}
|
||||
|
||||
ret_value get_err(void) { return _err; }
|
||||
|
||||
#include "parse.h"
|
||||
|
@ -629,7 +695,8 @@ private:
|
|||
void putf(floating_t value)
|
||||
{
|
||||
/* warning, caller must check object type before */
|
||||
number num(value);
|
||||
number num;
|
||||
num.set(value);
|
||||
_stack->push_back(&num, sizeof(number), cmd_number);
|
||||
}
|
||||
|
||||
|
@ -644,11 +711,21 @@ private:
|
|||
void putb(integer_t value)
|
||||
{
|
||||
/* warning, caller must check object type before */
|
||||
binary num(value);
|
||||
binary num;
|
||||
num.set(value);
|
||||
_stack->push_back(&num, sizeof(binary), cmd_binary);
|
||||
}
|
||||
|
||||
int stack_size()
|
||||
// care: return value must be used before pushing something else in stack
|
||||
char* getn()
|
||||
{
|
||||
/* warning, caller must check object type before */
|
||||
char* a = ((ostring*)_stack->back())->_value;
|
||||
_stack->pop_back();
|
||||
return a;
|
||||
}
|
||||
|
||||
int stack_size()
|
||||
{
|
||||
return _stack->size();
|
||||
}
|
||||
|
@ -737,7 +814,7 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||
}
|
||||
|
||||
// make program
|
||||
ret = program::parse(entry, prog);
|
||||
ret = program::parse(entry.c_str(), prog);
|
||||
if (ret == ret_ok)
|
||||
{
|
||||
string separator = "";
|
||||
|
|
Loading…
Reference in a new issue