mirror of
https://github.com/louisrubet/rpn
synced 2025-01-30 20:34:30 +01:00
#116: added do..unti
This commit is contained in:
parent
3472aebd88
commit
253dc0954b
6 changed files with 191 additions and 70 deletions
18
README.md
18
README.md
|
@ -154,14 +154,16 @@ rpn>
|
|||
|
||||
|keyword|description|
|
||||
|-|-|
|
||||
|if| test-instructions
|
||||
|then| true-instructions
|
||||
|else| false-instructions
|
||||
|end| (end of if structure)
|
||||
|start| repeat instructions several times
|
||||
|for| repeat instructions several times with variable
|
||||
|next| ex: ```1 10 start <instructions> next```
|
||||
|step| ex: ```1 100 start <instructions> 4 step```
|
||||
|if| if <test-instruction> then <true-instructions> else <false-instructions> end
|
||||
|then| used with if
|
||||
|else| used with if
|
||||
|end| used with various branch instructions
|
||||
|start| start> <end> start <instructions> next|<step> step
|
||||
|for| start> <end> for <variable> <instructions> next|<step> step
|
||||
|next| used with start and for
|
||||
|step| used with start and for
|
||||
|do| do <instructions> unti <condition> end
|
||||
|unti | used with do
|
||||
|
||||
#### store
|
||||
|
||||
|
|
|
@ -100,14 +100,16 @@ program::keyword_t program::s_keywords[] =
|
|||
|
||||
//BRANCH
|
||||
{ cmd_undef, "", NULL, "\nBRANCH"},
|
||||
{ cmd_branch, "if", (program_fn_t)&program::rpn_if, "<test-instructions>" },
|
||||
{ cmd_branch, "then", (program_fn_t)&program::rpn_then, "<true-instructions>" },
|
||||
{ cmd_branch, "else", (program_fn_t)&program::rpn_else, "<false-instructions>" },
|
||||
{ cmd_keyword, "end", &program::rpn_end, "(end of if structure)" },
|
||||
{ cmd_branch, "start", (program_fn_t)&program::rpn_start, "repeat instructions several times" },
|
||||
{ cmd_branch, "for", (program_fn_t)&program::rpn_for, "repeat instructions several times with variable" },
|
||||
{ cmd_branch, "next", (program_fn_t)&program::rpn_next, "ex: 1 10 start <instructions> next" },
|
||||
{ cmd_branch, "step", (program_fn_t)&program::rpn_step, "ex: 1 100 start <instructions> 4 step" },
|
||||
{ cmd_branch, "if", (program_fn_t)&program::rpn_if, "if <test-instruction> then <true-instructions> else <false-instructions> end" },
|
||||
{ cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if" },
|
||||
{ cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if" },
|
||||
{ cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions" },
|
||||
{ cmd_branch, "start", (program_fn_t)&program::rpn_start, "<start> <end> start <instructions> next|<step> step" },
|
||||
{ cmd_branch, "for", (program_fn_t)&program::rpn_for, "<start> <end> for <variable> <instructions> next|<step> step" },
|
||||
{ cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for" },
|
||||
{ cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for" },
|
||||
{ cmd_branch, "do", (program_fn_t)&program::rpn_do, "do <instructions> unti <condition> end" },
|
||||
{ cmd_branch, "unti", (program_fn_t)&program::rpn_unti, "used with do" },
|
||||
|
||||
//STORE
|
||||
{ cmd_undef, "", NULL, "\nSTORE"},
|
||||
|
|
153
src/program.hpp
153
src/program.hpp
|
@ -28,11 +28,12 @@ using namespace std;
|
|||
//
|
||||
struct if_layout_t
|
||||
{
|
||||
if_layout_t():index_then(-1),index_else(-1),index_end(-1) { }
|
||||
int index_if;
|
||||
int index_then;
|
||||
if_layout_t():index_then_or_unti(-1),index_else(-1),index_end(-1),is_do_unti(false) { }
|
||||
int index_if_or_do;
|
||||
int index_then_or_unti;
|
||||
int index_else;
|
||||
int index_end;
|
||||
bool is_do_unti;
|
||||
};
|
||||
|
||||
// program
|
||||
|
@ -168,52 +169,13 @@ public:
|
|||
for(int i=0; i<(int)size(); i++)
|
||||
{
|
||||
int type = seq_type(i);
|
||||
if (type == cmd_keyword)
|
||||
{
|
||||
keyword* k = (keyword*)seq_obj(i);
|
||||
if (compare_keyword(k, "end", 3))
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
next = -1;
|
||||
|
||||
if (layout_index<0)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("missing if before end");
|
||||
return ret_syntax;
|
||||
}
|
||||
if (vlayout[layout_index].index_end != -1)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("duplicate end");
|
||||
return ret_syntax;
|
||||
}
|
||||
if (vlayout[layout_index].index_else != -1)
|
||||
//fill 'end' branch of 'else'
|
||||
((branch*)seq_obj(vlayout[layout_index].index_else))->arg2 = i;
|
||||
else
|
||||
{
|
||||
//fill 'end' branch of 'then'
|
||||
if (vlayout[layout_index].index_then != -1)
|
||||
((branch*)seq_obj(vlayout[layout_index].index_then))->arg2 = i;
|
||||
else
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("missing then before end");
|
||||
return ret_syntax;
|
||||
}
|
||||
}
|
||||
layout_index--;
|
||||
}
|
||||
}
|
||||
else if (type == cmd_branch)
|
||||
if (type == cmd_branch)
|
||||
{
|
||||
branch* k = (branch*)seq_obj(i);
|
||||
if (compare_branch(k, "if", 2))
|
||||
{
|
||||
if_layout_t layout;
|
||||
layout.index_if = i;
|
||||
layout.index_if_or_do = i;
|
||||
vlayout.push_back(layout);
|
||||
layout_index++;
|
||||
}
|
||||
|
@ -236,15 +198,15 @@ public:
|
|||
show_syntax_error("missing if before then");
|
||||
return ret_syntax;
|
||||
}
|
||||
if (vlayout[layout_index].index_then != -1)
|
||||
if (vlayout[layout_index].index_then_or_unti != -1)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("duplicate then");
|
||||
return ret_syntax;
|
||||
}
|
||||
vlayout[layout_index].index_then = i;
|
||||
vlayout[layout_index].index_then_or_unti = i;
|
||||
k->arg1 = next;
|
||||
k->arg3 = vlayout[layout_index].index_if;
|
||||
k->arg3 = vlayout[layout_index].index_if_or_do;
|
||||
}
|
||||
else if (compare_branch(k, "else", 4))
|
||||
{
|
||||
|
@ -265,7 +227,7 @@ public:
|
|||
show_syntax_error("missing if before else");
|
||||
return ret_syntax;
|
||||
}
|
||||
if (vlayout[layout_index].index_then == -1)
|
||||
if (vlayout[layout_index].index_then_or_unti == -1)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("missing then before else");
|
||||
|
@ -279,13 +241,11 @@ public:
|
|||
}
|
||||
vlayout[layout_index].index_else = i;
|
||||
k->arg1 = next;// fill branch1 (if was false) of 'else'
|
||||
k->arg3 = vlayout[layout_index].index_if;
|
||||
((branch*)seq_obj(vlayout[layout_index].index_then))->arg2 = next;// fill branch2 (if was false) of 'then'
|
||||
k->arg3 = vlayout[layout_index].index_if_or_do;
|
||||
((branch*)seq_obj(vlayout[layout_index].index_then_or_unti))->arg2 = next;// fill branch2 (if was false) of 'then'
|
||||
}
|
||||
else if (compare_branch(k, "start", 5))
|
||||
{
|
||||
vstartindex.push_back(i);
|
||||
}
|
||||
else if (compare_branch(k, "for", 3))
|
||||
{
|
||||
vstartindex.push_back(i);
|
||||
|
@ -319,6 +279,95 @@ public:
|
|||
{
|
||||
k->arg1 = i;// arg1 is '->' command index in program
|
||||
}
|
||||
else if (compare_branch(k, "do", 2))
|
||||
{
|
||||
if_layout_t layout;
|
||||
layout.index_if_or_do = i;
|
||||
layout.is_do_unti = true;
|
||||
vlayout.push_back(layout);
|
||||
layout_index++;
|
||||
}
|
||||
else if (compare_branch(k, "unti", 2))
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
next = -1;
|
||||
|
||||
// nothing after 'unti' -> error
|
||||
if (next == -1)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("missing end after unti");
|
||||
return ret_syntax;
|
||||
}
|
||||
if (layout_index<0)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("missing do before unti");
|
||||
return ret_syntax;
|
||||
}
|
||||
if (vlayout[layout_index].index_then_or_unti != -1)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("duplicate unti");
|
||||
return ret_syntax;
|
||||
}
|
||||
}
|
||||
else if (compare_branch(k, "end", 3))
|
||||
{
|
||||
int next = i + 1;
|
||||
if (next >= (int)size())
|
||||
next = -1;
|
||||
|
||||
if (layout_index<0)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("missing branch instruction before end");
|
||||
return ret_syntax;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vlayout[layout_index].is_do_unti)
|
||||
{
|
||||
// this end closes a do..unti
|
||||
if (vlayout[layout_index].index_end != -1)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("duplicate end");
|
||||
return ret_syntax;
|
||||
}
|
||||
|
||||
k->arg1 = vlayout[layout_index].index_if_or_do + 1;
|
||||
layout_index--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this end closes an if..then..(else)
|
||||
if (vlayout[layout_index].index_end != -1)
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("duplicate end");
|
||||
return ret_syntax;
|
||||
}
|
||||
if (vlayout[layout_index].index_else != -1)
|
||||
//fill 'end' branch of 'else'
|
||||
((branch*)seq_obj(vlayout[layout_index].index_else))->arg2 = i;
|
||||
else
|
||||
{
|
||||
//fill 'end' branch of 'then'
|
||||
if (vlayout[layout_index].index_then_or_unti != -1)
|
||||
((branch*)seq_obj(vlayout[layout_index].index_then_or_unti))->arg2 = i;
|
||||
else
|
||||
{
|
||||
// error: show it
|
||||
show_syntax_error("missing then before end");
|
||||
return ret_syntax;
|
||||
}
|
||||
}
|
||||
layout_index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (layout_index >= 0)
|
||||
|
|
|
@ -41,9 +41,36 @@ int rpn_else(branch& myobj)
|
|||
return myobj.arg1;
|
||||
}
|
||||
|
||||
void rpn_end(void)
|
||||
int rpn_end(branch& myobj)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
// arg1 = index of do+1 in case of do..unti..end
|
||||
if (myobj.arg1 != -1)
|
||||
{
|
||||
// in a template do..unti..end
|
||||
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
|
||||
|
||||
// check arg
|
||||
number* arg = (number*)_stack->pop_back();
|
||||
if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0)
|
||||
ret = myobj.arg1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpn_do(branch& myobj)
|
||||
{
|
||||
// nothing
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpn_unti(branch& myobj)
|
||||
{
|
||||
// nothing
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpn_start(branch& myobj)
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
_base = (char*)realloc(_base, _total_size);
|
||||
|
||||
_current = _base + (_current - old_base);
|
||||
data_is_reallocated = true;
|
||||
data_is_reallocated = true;
|
||||
}
|
||||
|
||||
// manage pointers memory allocation (add one page if needed)
|
||||
|
|
|
@ -224,3 +224,44 @@ erase
|
|||
step
|
||||
-> error should be 11
|
||||
erase
|
||||
|
||||
# do..unti (1)
|
||||
do 'ok' unti 1 end
|
||||
-> stack should be 'ok'
|
||||
erase
|
||||
|
||||
# do..unti (2)
|
||||
do unti 1 end
|
||||
-> stack size should be 0
|
||||
erase
|
||||
|
||||
# do..unti (3)
|
||||
1 'a' sto do a unti a 0 > end
|
||||
-> stack should be 1
|
||||
erase
|
||||
|
||||
# do..unti (4)
|
||||
1 'a' sto do a 'a' 1 sto+ unti a 3 > end
|
||||
-> stack should be 1, 2, 3
|
||||
erase
|
||||
|
||||
# do..unti (5)
|
||||
"" 0 'a' sto do 'a' 1 sto+ 0 a for b b ->str + next unti a 3 > end
|
||||
-> stack should be "01012012301234"
|
||||
erase
|
||||
|
||||
# do..unti error case (1)
|
||||
do
|
||||
-> error should be 11
|
||||
|
||||
# do..unti error case (2)
|
||||
unti
|
||||
-> error should be 11
|
||||
|
||||
# do..unti error case (3)
|
||||
do 3 unti
|
||||
-> error should be 11
|
||||
|
||||
# do..unti error case (4)
|
||||
unti 1 end
|
||||
-> error should be 11
|
||||
|
|
Loading…
Add table
Reference in a new issue