fix: break and continue
This commit is contained in:
parent
c3af6bd5ca
commit
bcaf2cb3b7
4 changed files with 135 additions and 83 deletions
|
@ -1,7 +1,14 @@
|
|||
# show case of 'continue' and 'break' keyword in their natural environment
|
||||
set i to 0
|
||||
while 1 do
|
||||
if i > 10 then
|
||||
break
|
||||
end
|
||||
if i = 5 then
|
||||
set i to i+1
|
||||
continue
|
||||
end
|
||||
print_number(i)
|
||||
set i to i+1
|
||||
end
|
||||
print_number(i)
|
||||
|
|
|
@ -360,12 +360,96 @@ int process_line(struct StateContainer* state, char* str)
|
|||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("recognize end state->blockStackAnchor: %d \n", state->blockStackAnchor);
|
||||
if (state->skipping && int_stack_length(state->blockStack) == state->blockStackAnchor) {
|
||||
// end of skipping
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("end of skipping \n");
|
||||
state->skipping = 0;
|
||||
}
|
||||
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct IfStatement ifStatementParsing;
|
||||
byte ifRecognized = recognize_if_statement(str, &ifStatementParsing);
|
||||
|
||||
struct WhileStatement whileStatementParsing;
|
||||
byte whileRecognized = recognize_while_statement(str, &whileStatementParsing);
|
||||
|
||||
if (ifRecognized) {
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("If statement recognized express (%d:%d)\n", ifStatementParsing.expression_start, ifStatementParsing.expression_stop);
|
||||
|
||||
int_stack_push(state->blockStack, BLOCK_IF);
|
||||
if (state->skipping) {
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// expression to evaluate
|
||||
int expressLen = ifStatementParsing.expression_stop - ifStatementParsing.expression_start;
|
||||
char dest[len];
|
||||
str_extract((char*) &dest, str, ifStatementParsing.expression_start, expressLen);
|
||||
// printf("expression to eval in if '%s' \n", dest);
|
||||
int res;
|
||||
byte resType;
|
||||
int evalStat = evaluate(state, (char*) &dest, &res, &resType);
|
||||
if (evalStat != 0) {
|
||||
printf("Syntax error for line \"%s\"\n", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte doFollow = convert_to_bool(resType, res);
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("Got %s, doFollow: %d \n", get_repr(resType, &res), doFollow);
|
||||
|
||||
if (!doFollow) {
|
||||
state->blockStackAnchor = int_stack_length(state->blockStack)-1;
|
||||
state->skipping = 1;
|
||||
}
|
||||
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (whileRecognized) {
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("While statement recognized express (%d:%d)\n", whileStatementParsing.expression_start, whileStatementParsing.expression_stop);
|
||||
|
||||
int_stack_push(state->blockStack, BLOCK_WHILE);
|
||||
if (state->skipping) {
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// expression to evaluate
|
||||
int expressLen = whileStatementParsing.expression_stop - whileStatementParsing.expression_start;
|
||||
char dest[len];
|
||||
str_extract((char*) &dest, str, whileStatementParsing.expression_start, expressLen);
|
||||
// printf("expression to eval in if '%s' \n", dest);
|
||||
int res;
|
||||
byte resType;
|
||||
int evalStat = evaluate(state, (char*) &dest, &res, &resType);
|
||||
if (evalStat != 0) {
|
||||
printf("Syntax error for line \"%s\"\n", str);
|
||||
return 0;
|
||||
}
|
||||
byte doFollow = convert_to_bool(resType, res);
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("Got %s, doFollow: %d \n", get_repr(resType, &res), doFollow);
|
||||
|
||||
if (doFollow) {
|
||||
// follow the line
|
||||
int_stack_push(state->loopStack, state->linePtr);
|
||||
}
|
||||
if (!doFollow) {
|
||||
state->blockStackAnchor = int_stack_length(state->blockStack)-1;
|
||||
state->skipping = 1;
|
||||
}
|
||||
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
if (state->skipping) {
|
||||
// we've finish to analyse structure-aware blocks
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (recognize_word(str, "continue")) {
|
||||
int lastLoopLine;
|
||||
if (!int_stack_pop(state->loopStack, &lastLoopLine)) {
|
||||
|
@ -400,23 +484,13 @@ int process_line(struct StateContainer* state, char* str)
|
|||
if (state->blockStack->data[lastLoopAnchor] == BLOCK_WHILE) break;
|
||||
lastLoopAnchor--;
|
||||
}
|
||||
state->blockStackAnchor = lastLoopAnchor+1;
|
||||
state->blockStackAnchor = lastLoopAnchor;
|
||||
state->skipping = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct IfStatement ifStatementParsing;
|
||||
byte ifRecognized = recognize_if_statement(str, &ifStatementParsing);
|
||||
|
||||
struct WhileStatement whileStatementParsing;
|
||||
byte whileRecognized = recognize_while_statement(str, &whileStatementParsing);
|
||||
|
||||
if (state->skipping) {
|
||||
// we've finish to analyse structure-aware blocks
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct SetStatement setStatementParsing;
|
||||
if (recognize_set_statement(str, &setStatementParsing)) {
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) {
|
||||
|
@ -454,69 +528,6 @@ int process_line(struct StateContainer* state, char* str)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (ifRecognized) {
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("If statement recognized express (%d:%d)\n", ifStatementParsing.expression_start, ifStatementParsing.expression_stop);
|
||||
|
||||
// expression to evaluate
|
||||
int expressLen = ifStatementParsing.expression_stop - ifStatementParsing.expression_start;
|
||||
char dest[len];
|
||||
str_extract((char*) &dest, str, ifStatementParsing.expression_start, expressLen);
|
||||
// printf("expression to eval in if '%s' \n", dest);
|
||||
int res;
|
||||
byte resType;
|
||||
int evalStat = evaluate(state, (char*) &dest, &res, &resType);
|
||||
if (evalStat != 0) {
|
||||
printf("Syntax error for line \"%s\"\n", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte doFollow = convert_to_bool(resType, res);
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("Got %s, doFollow: %d \n", get_repr(resType, &res), doFollow);
|
||||
|
||||
if (!doFollow) {
|
||||
state->blockStackAnchor = int_stack_length(state->blockStack);
|
||||
state->skipping = 1;
|
||||
}
|
||||
|
||||
int_stack_push(state->blockStack, BLOCK_IF);
|
||||
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (whileRecognized) {
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("While statement recognized express (%d:%d)\n", whileStatementParsing.expression_start, whileStatementParsing.expression_stop);
|
||||
|
||||
// expression to evaluate
|
||||
int expressLen = whileStatementParsing.expression_stop - whileStatementParsing.expression_start;
|
||||
char dest[len];
|
||||
str_extract((char*) &dest, str, whileStatementParsing.expression_start, expressLen);
|
||||
// printf("expression to eval in if '%s' \n", dest);
|
||||
int res;
|
||||
byte resType;
|
||||
int evalStat = evaluate(state, (char*) &dest, &res, &resType);
|
||||
if (evalStat != 0) {
|
||||
printf("Syntax error for line \"%s\"\n", str);
|
||||
return 0;
|
||||
}
|
||||
byte doFollow = convert_to_bool(resType, res);
|
||||
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("Got %s, doFollow: %d \n", get_repr(resType, &res), doFollow);
|
||||
|
||||
if (doFollow) {
|
||||
// follow the line
|
||||
int_stack_push(state->loopStack, state->linePtr);
|
||||
}
|
||||
if (!doFollow) {
|
||||
state->blockStackAnchor = int_stack_length(state->blockStack);
|
||||
state->skipping = 1;
|
||||
}
|
||||
|
||||
int_stack_push(state->blockStack, BLOCK_WHILE);
|
||||
|
||||
state->linePtr++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// we evaluate but we dont care about the result
|
||||
int res;
|
||||
byte resType;
|
||||
|
|
16
src/main.c
16
src/main.c
|
@ -17,13 +17,13 @@
|
|||
#define INTERACTIVE_FLAG 8
|
||||
#define STDIN_EXP_FLAG 16
|
||||
|
||||
int help_mode() {
|
||||
char* helpStr = "Usage: langatator [options] [file]\n"
|
||||
int help_mode(char* cmdName) {
|
||||
char* helpStr = "Usage: %s [options] [file]\n"
|
||||
" -h --help print this usage and exit\n"
|
||||
" -v --version print version information and exit\n"
|
||||
" -i --interactive force interactive mode\n"
|
||||
" -e --stdin-expression evaluate expression from stdin\n";
|
||||
printf(helpStr);
|
||||
printf(helpStr, cmdName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ int file_mode(char* fileName) {
|
|||
FILE* f = fopen(fileName, "rb");
|
||||
|
||||
if (!f) {
|
||||
printf(stderr, "Cannot load file '%s' status: %d\n", fileName, f);
|
||||
fprintf(stderr, "Cannot load file '%s' status: %d\n", fileName, (int) f);
|
||||
return 1;
|
||||
}
|
||||
fseek(f, 0, SEEK_END);
|
||||
|
@ -56,7 +56,7 @@ int file_mode(char* fileName) {
|
|||
|
||||
char* buff = (char*) malloc(length);
|
||||
if (!buff) {
|
||||
printf(stderr, "Could not allocate buffer to process file content\n");
|
||||
fprintf(stderr, "Could not allocate buffer to process file content\n");
|
||||
return 1;
|
||||
}
|
||||
if (buff) {
|
||||
|
@ -96,7 +96,7 @@ int main (int argc, char** argv) {
|
|||
}
|
||||
// no flag match
|
||||
if (str_starts_with("--", argv[i])) {
|
||||
printf(stderr, "Invalid flag '%s'\n", argv[i]);
|
||||
fprintf(stderr, "Invalid flag '%s'\n", argv[i]);
|
||||
return 1;
|
||||
}
|
||||
nonFlagArgumentCount++;
|
||||
|
@ -104,11 +104,11 @@ int main (int argc, char** argv) {
|
|||
}
|
||||
if (nonFlagArgumentCount == 1) return file_mode(argv[nonFlagArgumentPos]);
|
||||
|
||||
if (flags & HELP_FLAG) return help_mode();
|
||||
if (flags & HELP_FLAG) return help_mode(cmdName);
|
||||
if (flags & VERSION_FLAG) return version_mode();
|
||||
if (flags & INTERACTIVE_FLAG) return interactive_mode();
|
||||
if (flags & STDIN_EXP_FLAG) return stdin_expression_mode();
|
||||
|
||||
help_mode();
|
||||
help_mode(cmdName);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -115,4 +115,38 @@ void test_line_processing()
|
|||
assert(!state2->skipping);
|
||||
printf("got i: %d \n", var_store_get_int(state2->varStore, "i"));
|
||||
assert(9 == var_store_get_int(state2->varStore, "i"));
|
||||
|
||||
// test break keyword
|
||||
char* lines5 = "set i to 0\n"
|
||||
"while 1 do\n"
|
||||
" if (i = 10) then\n"
|
||||
" break\n"
|
||||
" end\n"
|
||||
" set i to i+1\n"
|
||||
"end\n";
|
||||
process_script(state2, lines5);
|
||||
|
||||
assert(!state2->skipping);
|
||||
printf("got i: %d \n", var_store_get_int(state2->varStore, "i"));
|
||||
assert(10 == var_store_get_int(state2->varStore, "i"));
|
||||
|
||||
// test continue keyword
|
||||
char* lines6 = "set sum to 0\n"
|
||||
"set i to 0\n"
|
||||
"while 1 do\n"
|
||||
" if (i = 5) then\n"
|
||||
" set i to i+1\n"
|
||||
" continue\n"
|
||||
" end\n"
|
||||
" if (i = 10) then\n"
|
||||
" break\n"
|
||||
" end\n"
|
||||
" set sum to sum+1\n"
|
||||
" set i to i+1\n"
|
||||
"end\n";
|
||||
process_script(state2, lines6);
|
||||
|
||||
assert(!state2->skipping);
|
||||
assert(10 == var_store_get_int(state2->varStore, "i"));
|
||||
assert(9 == var_store_get_int(state2->varStore, "sum"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue