From 253dc0954b0826a53cfe99c4eb016971fb37c729 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sat, 10 Jun 2017 11:43:10 +0200 Subject: [PATCH] #116: added do..unti --- README.md | 18 +++--- src/program.cpp | 18 +++--- src/program.hpp | 153 ++++++++++++++++++++++++++++++--------------- src/rpn-branch.hpp | 29 ++++++++- src/stack.hpp | 2 +- test/04-branch.txt | 41 ++++++++++++ 6 files changed, 191 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 3f92b27..4383101 100644 --- a/README.md +++ b/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 next``` -|step| ex: ```1 100 start 4 step``` +|if| if then else end +|then| used with if +|else| used with if +|end| used with various branch instructions +|start| start> start next| step +|for| start> for next| step +|next| used with start and for +|step| used with start and for +|do| do unti end +|unti | used with do #### store diff --git a/src/program.cpp b/src/program.cpp index a7b3912..59e6d44 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -100,14 +100,16 @@ program::keyword_t program::s_keywords[] = //BRANCH { cmd_undef, "", NULL, "\nBRANCH"}, - { cmd_branch, "if", (program_fn_t)&program::rpn_if, "" }, - { cmd_branch, "then", (program_fn_t)&program::rpn_then, "" }, - { cmd_branch, "else", (program_fn_t)&program::rpn_else, "" }, - { 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 next" }, - { cmd_branch, "step", (program_fn_t)&program::rpn_step, "ex: 1 100 start 4 step" }, + { cmd_branch, "if", (program_fn_t)&program::rpn_if, "if then else 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 next| step" }, + { cmd_branch, "for", (program_fn_t)&program::rpn_for, " for next| 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 unti end" }, + { cmd_branch, "unti", (program_fn_t)&program::rpn_unti, "used with do" }, //STORE { cmd_undef, "", NULL, "\nSTORE"}, diff --git a/src/program.hpp b/src/program.hpp index 6f115e0..0cc08b5 100644 --- a/src/program.hpp +++ b/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) diff --git a/src/rpn-branch.hpp b/src/rpn-branch.hpp index 4c46b08..30f583a 100644 --- a/src/rpn-branch.hpp +++ b/src/rpn-branch.hpp @@ -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) diff --git a/src/stack.hpp b/src/stack.hpp index 5642343..d92fd0f 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -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) diff --git a/test/04-branch.txt b/test/04-branch.txt index eed00a3..4c8bec4 100644 --- a/test/04-branch.txt +++ b/test/04-branch.txt @@ -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