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
---
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>
$label <identifier>
== <identifier> ==
```
## Goto a label
```
-> <identifier>
```
## Example
@ -18,7 +23,8 @@ $label <identifier>
for i in range(10):
for j 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 **/
"class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "yield",
"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);
} break;
/*************************************************/
case TK("$label"): {
if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
case TK("=="): {
consume(TK("@id"));
if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
bool ok = ctx()->add_label(prev().str());
consume(TK("=="));
if(!ok) SyntaxError("label " + prev().str().escape() + " already exists");
consume_end_stmt();
} break;
case TK("$goto"):
if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
case TK("->"):
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);
consume_end_stmt();
break;

View File

@ -325,16 +325,6 @@ static bool is_unicode_Lo_char(uint32_t c) {
eat_spaces();
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;

View File

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