reimpl goto

This commit is contained in:
blueloveTH 2023-09-24 13:47:47 +08:00
parent 5e11b9bf53
commit dd6e8fab9b
5 changed files with 21 additions and 26 deletions

View File

@ -3,13 +3,18 @@ icon: dot
title: Goto Statement title: Goto Statement
--- ---
pkpy supports `goto` and `label` just like C. You are allowed to change the control flow unconditionally. pkpy supports goto/label just like C. You are allowed to **change the control flow unconditionally**.
## Syntax ## Define a label
``` ```
$goto <identifier> == <identifier> ==
$label <identifier> ```
## Goto a label
```
-> <identifier>
``` ```
## Example ## Example
@ -18,7 +23,8 @@ $label <identifier>
for i in range(10): for i in range(10):
for j in range(10): for j in range(10):
for k in range(10): for k in range(10):
$goto exit -> exit
$label exit == exit ==
print('exit')
``` ```

View File

@ -22,8 +22,6 @@ constexpr const char* kTokens[] = {
".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}", ".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}",
"**", "=", ">", "<", "..", "...", "->", "?", "@", "==", "!=", ">=", "<=", "**", "=", ">", "<", "..", "...", "->", "?", "@", "==", "!=", ">=", "<=",
"++", "--", "~", "++", "--", "~",
/** SPEC_BEGIN **/
"$goto", "$label",
/** KW_BEGIN **/ /** KW_BEGIN **/
"class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "yield", "class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "yield",
"None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally", "None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally",

View File

@ -844,16 +844,17 @@ __EAT_DOTS_END:
ctx()->emit(OP_WITH_EXIT, BC_NOARG, prev().line); ctx()->emit(OP_WITH_EXIT, BC_NOARG, prev().line);
} break; } break;
/*************************************************/ /*************************************************/
case TK("$label"): { case TK("=="): {
if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
consume(TK("@id")); consume(TK("@id"));
if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
bool ok = ctx()->add_label(prev().str()); bool ok = ctx()->add_label(prev().str());
consume(TK("=="));
if(!ok) SyntaxError("label " + prev().str().escape() + " already exists"); if(!ok) SyntaxError("label " + prev().str().escape() + " already exists");
consume_end_stmt(); consume_end_stmt();
} break; } break;
case TK("$goto"): case TK("->"):
if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
consume(TK("@id")); consume(TK("@id"));
if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
ctx()->emit(OP_GOTO, StrName(prev().str()).index, prev().line); ctx()->emit(OP_GOTO, StrName(prev().str()).index, prev().line);
consume_end_stmt(); consume_end_stmt();
break; break;

View File

@ -325,16 +325,6 @@ static bool is_unicode_Lo_char(uint32_t c) {
eat_spaces(); eat_spaces();
return true; return true;
} }
case '$': {
for(int i=TK("$goto"); i<=TK("$label"); i++){
// +1 to skip the '$'
if(match_string(TK_STR(i) + 1)){
add_token((TokenIndex)i);
return true;
}
}
SyntaxError("invalid special token");
} return false;
case '%': add_token_2('=', TK("%"), TK("%=")); return true; case '%': add_token_2('=', TK("%"), TK("%=")); return true;
case '&': add_token_2('=', TK("&"), TK("&=")); return true; case '&': add_token_2('=', TK("&"), TK("&=")); return true;
case '|': add_token_2('=', TK("|"), TK("|=")); return true; case '|': add_token_2('=', TK("|"), TK("|=")); return true;

View File

@ -2,9 +2,9 @@ a = []
for i in range(10): # [0] for i in range(10): # [0]
for j in range(10): # [0-0] for j in range(10): # [0-0]
$goto test -> test
print(2) print(2)
$label test == test ==
a.append(i) a.append(i)
for k in range(5): # [0-1] for k in range(5): # [0-1]
for t in range(7): # [0-1-0] for t in range(7): # [0-1-0]
@ -16,7 +16,7 @@ b = False
for i in range(10): # [1] for i in range(10): # [1]
for j in range(10): # [1-0] for j in range(10): # [1-0]
$goto out -> out
b = True b = True
$label out == out ==
assert not b assert not b