#116: added do..unti

This commit is contained in:
Louis Rubet 2017-06-10 11:43:10 +02:00
parent 3472aebd88
commit 253dc0954b
6 changed files with 191 additions and 70 deletions

View file

@ -154,14 +154,16 @@ rpn>
|keyword|description| |keyword|description|
|-|-| |-|-|
|if| test-instructions |if| if <test-instruction> then <true-instructions> else <false-instructions> end
|then| true-instructions |then| used with if
|else| false-instructions |else| used with if
|end| (end of if structure) |end| used with various branch instructions
|start| repeat instructions several times |start| start> <end> start <instructions> next|<step> step
|for| repeat instructions several times with variable |for| start> <end> for <variable> <instructions> next|<step> step
|next| ex: ```1 10 start <instructions> next``` |next| used with start and for
|step| ex: ```1 100 start <instructions> 4 step``` |step| used with start and for
|do| do <instructions> unti <condition> end
|unti | used with do
#### store #### store

View file

@ -100,14 +100,16 @@ program::keyword_t program::s_keywords[] =
//BRANCH //BRANCH
{ cmd_undef, "", NULL, "\nBRANCH"}, { cmd_undef, "", NULL, "\nBRANCH"},
{ cmd_branch, "if", (program_fn_t)&program::rpn_if, "<test-instructions>" }, { 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, "<true-instructions>" }, { cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if" },
{ cmd_branch, "else", (program_fn_t)&program::rpn_else, "<false-instructions>" }, { cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if" },
{ cmd_keyword, "end", &program::rpn_end, "(end of if structure)" }, { cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions" },
{ cmd_branch, "start", (program_fn_t)&program::rpn_start, "repeat instructions several times" }, { 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, "repeat instructions several times with variable" }, { 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, "ex: 1 10 start <instructions> next" }, { cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for" },
{ cmd_branch, "step", (program_fn_t)&program::rpn_step, "ex: 1 100 start <instructions> 4 step" }, { 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 //STORE
{ cmd_undef, "", NULL, "\nSTORE"}, { cmd_undef, "", NULL, "\nSTORE"},

View file

@ -28,11 +28,12 @@ using namespace std;
// //
struct if_layout_t struct if_layout_t
{ {
if_layout_t():index_then(-1),index_else(-1),index_end(-1) { } if_layout_t():index_then_or_unti(-1),index_else(-1),index_end(-1),is_do_unti(false) { }
int index_if; int index_if_or_do;
int index_then; int index_then_or_unti;
int index_else; int index_else;
int index_end; int index_end;
bool is_do_unti;
}; };
// program // program
@ -168,52 +169,13 @@ public:
for(int i=0; i<(int)size(); i++) for(int i=0; i<(int)size(); i++)
{ {
int type = seq_type(i); int type = seq_type(i);
if (type == cmd_keyword) if (type == cmd_branch)
{
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)
{ {
branch* k = (branch*)seq_obj(i); branch* k = (branch*)seq_obj(i);
if (compare_branch(k, "if", 2)) if (compare_branch(k, "if", 2))
{ {
if_layout_t layout; if_layout_t layout;
layout.index_if = i; layout.index_if_or_do = i;
vlayout.push_back(layout); vlayout.push_back(layout);
layout_index++; layout_index++;
} }
@ -236,15 +198,15 @@ public:
show_syntax_error("missing if before then"); show_syntax_error("missing if before then");
return ret_syntax; return ret_syntax;
} }
if (vlayout[layout_index].index_then != -1) if (vlayout[layout_index].index_then_or_unti != -1)
{ {
// error: show it // error: show it
show_syntax_error("duplicate then"); show_syntax_error("duplicate then");
return ret_syntax; return ret_syntax;
} }
vlayout[layout_index].index_then = i; vlayout[layout_index].index_then_or_unti = i;
k->arg1 = next; 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)) else if (compare_branch(k, "else", 4))
{ {
@ -265,7 +227,7 @@ public:
show_syntax_error("missing if before else"); show_syntax_error("missing if before else");
return ret_syntax; return ret_syntax;
} }
if (vlayout[layout_index].index_then == -1) if (vlayout[layout_index].index_then_or_unti == -1)
{ {
// error: show it // error: show it
show_syntax_error("missing then before else"); show_syntax_error("missing then before else");
@ -279,13 +241,11 @@ public:
} }
vlayout[layout_index].index_else = i; vlayout[layout_index].index_else = i;
k->arg1 = next;// fill branch1 (if was false) of 'else' k->arg1 = next;// fill branch1 (if was false) of 'else'
k->arg3 = vlayout[layout_index].index_if; k->arg3 = vlayout[layout_index].index_if_or_do;
((branch*)seq_obj(vlayout[layout_index].index_then))->arg2 = next;// fill branch2 (if was false) of 'then' ((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)) else if (compare_branch(k, "start", 5))
{
vstartindex.push_back(i); vstartindex.push_back(i);
}
else if (compare_branch(k, "for", 3)) else if (compare_branch(k, "for", 3))
{ {
vstartindex.push_back(i); vstartindex.push_back(i);
@ -319,6 +279,95 @@ public:
{ {
k->arg1 = i;// arg1 is '->' command index in program 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) if (layout_index >= 0)

View file

@ -41,9 +41,36 @@ int rpn_else(branch& myobj)
return myobj.arg1; 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 // nothing
return -1;
}
int rpn_unti(branch& myobj)
{
// nothing
return -1;
} }
int rpn_start(branch& myobj) int rpn_start(branch& myobj)

View file

@ -74,7 +74,7 @@ public:
_base = (char*)realloc(_base, _total_size); _base = (char*)realloc(_base, _total_size);
_current = _base + (_current - old_base); _current = _base + (_current - old_base);
data_is_reallocated = true; data_is_reallocated = true;
} }
// manage pointers memory allocation (add one page if needed) // manage pointers memory allocation (add one page if needed)

View file

@ -224,3 +224,44 @@ erase
step step
-> error should be 11 -> error should be 11
erase 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