improve f-string

This commit is contained in:
blueloveTH 2023-11-22 06:16:05 +08:00
parent 787df86311
commit 2698040f52
2 changed files with 88 additions and 26 deletions

View File

@ -379,7 +379,7 @@ namespace pkpy{
} }
} }
// name or name.name // name or name.name
std::regex pattern(R"(^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*){0,1}$)"); PK_LOCAL_STATIC const std::regex pattern(R"(^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*){0,1}$)");
if(std::regex_match(expr.str(), pattern)){ if(std::regex_match(expr.str(), pattern)){
int dot = expr.index("."); int dot = expr.index(".");
if(dot < 0){ if(dot < 0){
@ -402,36 +402,73 @@ namespace pkpy{
void FStringExpr::emit_(CodeEmitContext* ctx){ void FStringExpr::emit_(CodeEmitContext* ctx){
VM* vm = ctx->vm; VM* vm = ctx->vm;
PK_LOCAL_STATIC const std::regex pattern(R"(\{(.*?)\})"); int i = 0; // left index
std::cregex_iterator begin(src.begin(), src.end(), pattern); int j = 0; // right index
std::cregex_iterator end; int count = 0; // how many string parts
int size = 0; bool flag = false; // true if we are in a expression
int i = 0;
for(auto it = begin; it != end; it++) { while(j < src.size){
std::cmatch m = *it; if(flag){
if (i < m.position()) { if(src[j] == '}'){
Str literal = src.substr(i, m.position() - i); // add expression
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line); Str expr = src.substr(i, j-i);
size++; int conon = expr.index(":");
} if(conon >= 0){
Str expr = m[1].str(); _load_simple_expr(ctx, expr.substr(0, conon));
int conon = expr.index(":"); Str spec = expr.substr(conon+1);
if(conon >= 0){ ctx->emit_(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line);
_load_simple_expr(ctx, expr.substr(0, conon)); }else{
Str spec = expr.substr(conon+1); _load_simple_expr(ctx, expr);
ctx->emit_(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line); }
flag = false;
count++;
}
}else{ }else{
_load_simple_expr(ctx, expr); if(src[j] == '{'){
// look at next char
if(j+1 < src.size && src[j+1] == '{'){
// {{ -> {
j++;
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR("{")), line);
count++;
}else{
// { -> }
flag = true;
i = j+1;
}
}else if(src[j] == '}'){
// look at next char
if(j+1 < src.size && src[j+1] == '}'){
// }} -> }
j++;
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR("}")), line);
count++;
}else{
// } -> error
// throw std::runtime_error("f-string: unexpected }");
// just ignore
}
}else{
// literal
i = j;
while(j < src.size && src[j] != '{' && src[j] != '}') j++;
Str literal = src.substr(i, j-i);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
count++;
continue; // skip j++
}
} }
size++; j++;
i = (int)(m.position() + m.length());
} }
if (i < src.length()) {
Str literal = src.substr(i, src.length() - i); if(flag){
// literal
Str literal = src.substr(i, src.size-i);
ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line); ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
size++; count++;
} }
ctx->emit_(OP_BUILD_STRING, size, line);
ctx->emit_(OP_BUILD_STRING, count, line);
} }

View File

@ -27,6 +27,10 @@ s = f'''->->{s}<-<-
assert s == '->->asdasd\nasds1321321321测试\\测试<-<-\n123\n' assert s == '->->asdasd\nasds1321321321测试\\测试<-<-\n123\n'
x = 1, 2, 3
assert f"""
a = {{{x[0]}, {x[1]}, {x[2]}}}""" == '\na = {1, 2, 3}'
assert r''' ' ''' == " ' " assert r''' ' ''' == " ' "
a = 10 a = 10
@ -85,6 +89,27 @@ assert f'{"test"!r:*^10}' == "**'test'**"
assert f'{"test"!r:*^11}' == "**'test'***" assert f'{"test"!r:*^11}' == "**'test'***"
assert f'{12345!r:0>10}' == "0000012345" assert f'{12345!r:0>10}' == "0000012345"
# test {{ and }}
assert f'' == ''
assert f'{{}}' == '{}'
assert f'{{{{}}}}' == '{{}}'
assert f'{{' == '{'
assert f'}}' == '}'
assert f'{{{{' == '{{'
assert f'}}}}' == '}}'
a = 123
assert f'={a}' == '=123'
assert f'{a}=' == '123='
assert f'--{a}--' == '--123--'
assert f'{{a}}' == '{a}'
assert f'{{{a}}}' == '{123}'
assert f'{{=}}{a}' == '{=}123'
assert f'{a}{{=}}' == '123{=}'
# assert f'}123' == '123' # ignore '}'
# assert f'{{{' == '{' # ignore '{'
class A: class A:
def __repr__(self): def __repr__(self):
return 'A()' return 'A()'