Add continue and break as aliases for skip/stop, also improve

keyword detection using a binary search
This commit is contained in:
Bruce Hill 2025-04-06 20:07:09 -04:00
parent 1d2e55f53d
commit 6cf980ea71
3 changed files with 28 additions and 13 deletions

View File

@ -86,11 +86,12 @@ func main()
>> [x*10 for x in my_numbers if x != 20]
= [100, 300]
# Loop control flow uses "skip" and "stop"
# Loop control flow uses "skip"/"continue" and "stop"/"break"
for x in my_numbers
for y in my_numbers
if x == y
skip
continue # This is the same as `skip`
# For readability, you can also use postfix conditionals:
skip if x == y
@ -99,6 +100,7 @@ func main()
# Skip or stop can specify a loop variable if you want to
# affect an enclosing loop:
stop x
break x # This is the same as `stop x`
# Tables are efficient hash maps
table := {"one"=1, "two"=2}

View File

@ -1338,7 +1338,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
}
}
if (env->loop_ctx)
code_err(ast, "This 'skip' is not inside any loop");
code_err(ast, "This is not inside any loop");
else if (target)
code_err(ast, "No loop target named '", target, "' was found");
else
@ -1367,7 +1367,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
}
}
if (env->loop_ctx)
code_err(ast, "This 'stop' is not inside any loop");
code_err(ast, "This is not inside any loop");
else if (target)
code_err(ast, "No loop target named '", target, "' was found");
else

View File

@ -61,10 +61,10 @@ int op_tightness[] = {
};
static const char *keywords[] = {
"yes", "xor", "while", "when", "use", "unless", "then", "struct", "stop", "skip", "return",
"or", "not", "none", "no", "mod1", "mod", "pass", "lang", "inline", "in", "if",
"func", "for", "extern", "extend", "enum", "else", "do", "deserialize", "defer", "and",
"_min_", "_max_", NULL,
"_max_", "_min_", "and", "break", "continue", "defer", "deserialize", "do", "else", "enum",
"extend", "extern", "for", "func", "if", "in", "inline", "lang", "mod", "mod1", "no", "none",
"not", "or", "pass", "return", "skip", "skip", "stop", "struct", "then", "unless", "use", "when",
"while", "xor", "yes",
};
enum {NORMAL_FUNCTION=0, EXTERN_FUNCTION=1};
@ -379,13 +379,26 @@ const char *get_word(const char **inout) {
return GC_strndup(word, (size_t)((const char*)pos - word));
}
static CONSTFUNC bool is_keyword(const char *word) {
int64_t lo = 0, hi = sizeof(keywords)/sizeof(keywords[0])-1;
while (lo <= hi) {
int64_t mid = (lo + hi) / 2;
int32_t cmp = strcmp(word, keywords[mid]);
if (cmp == 0)
return true;
else if (cmp > 0)
lo = mid + 1;
else if (cmp < 0)
hi = mid - 1;
}
return false;
}
const char *get_id(const char **inout) {
const char *pos = *inout;
const char *word = get_word(&pos);
if (!word) return word;
for (int i = 0; keywords[i]; i++)
if (strcmp(word, keywords[i]) == 0)
return NULL;
if (!word || is_keyword(word))
return NULL;
*inout = pos;
return word;
}
@ -1346,7 +1359,7 @@ PARSER(parse_defer) {
PARSER(parse_skip) {
const char *start = pos;
if (!match_word(&pos, "skip")) return NULL;
if (!match_word(&pos, "continue") && !match_word(&pos, "skip")) return NULL;
const char *target;
if (match_word(&pos, "for")) target = "for";
else if (match_word(&pos, "while")) target = "while";
@ -1358,7 +1371,7 @@ PARSER(parse_skip) {
PARSER(parse_stop) {
const char *start = pos;
if (!match_word(&pos, "stop")) return NULL;
if (!match_word(&pos, "stop") && !match_word(&pos, "break")) return NULL;
const char *target;
if (match_word(&pos, "for")) target = "for";
else if (match_word(&pos, "while")) target = "while";