Skip to content

Commit cfacf1e

Browse files
mrdaybirdAgent-Hellboy
authored andcommitted
Improving prefix-string parsing (fixes lcompilers#2339) (lcompilers#2511)
1 parent b40c654 commit cfacf1e

10 files changed

+78
-3
lines changed

src/lpython/parser/parser.yy

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ void yyerror(YYLTYPE *yyloc, LCompilers::LPython::Parser &p, const std::string &
179179
%token KW_MATCH
180180
%token KW_CASE
181181

182+
%token KW_STR_PREFIX
183+
%type <string> KW_STR_PREFIX
184+
182185
// Nonterminal tokens
183186

184187
%type <ast> script_unit
@@ -1102,9 +1105,9 @@ subscript
11021105

11031106
string
11041107
: string TK_STRING { $$ = STRING2($1, $2, @$); } // TODO
1105-
| string id TK_STRING { $$ = STRING4($1, STRING3($2, $3, @$), @$); }
1108+
| string KW_STR_PREFIX TK_STRING { $$ = STRING4($1, STRING3($2, $3, @$), @$); }
11061109
| TK_STRING { $$ = STRING1($1, @$); }
1107-
| id TK_STRING { $$ = STRING3($1, $2, @$); }
1110+
| KW_STR_PREFIX TK_STRING { $$ = STRING3($1, $2, @$); }
11081111
;
11091112

11101113
lambda_parameter

src/lpython/parser/semantics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ static inline ast_t* concat_string(Allocator &al, Location &l,
800800
#define INTEGER(x, l) make_ConstantInt_t(p.m_a, l, x, nullptr)
801801
#define STRING1(x, l) make_ConstantStr_t(p.m_a, l, str_unescape_c(p.m_a, x), nullptr)
802802
#define STRING2(x, y, l) concat_string(p.m_a, l, EXPR(x), str_unescape_c(p.m_a, y), nullptr)
803-
#define STRING3(id, x, l) PREFIX_STRING(p.m_a, l, name2char(id), x.c_str(p.m_a))
803+
#define STRING3(prefix, x, l) PREFIX_STRING(p.m_a, l, prefix.c_str(p.m_a), x.c_str(p.m_a))
804804
#define STRING4(x, s, l) concat_string(p.m_a, l, EXPR(x), "", EXPR(s))
805805
#define FLOAT(x, l) make_ConstantFloat_t(p.m_a, l, x, nullptr)
806806
#define COMPLEX(x, l) make_ConstantComplex_t(p.m_a, l, 0, x, nullptr)

src/lpython/parser/tokenizer.re

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,19 @@ int Tokenizer::lex(Allocator &al, YYSTYPE &yylval, Location &loc, diag::Diagnost
435435
}
436436
}
437437
438+
[rR][bB] | [bB][rR]
439+
| [fF][rR] | [rR][fF]
440+
| [rR] | [bB] | [fF] | [uU]
441+
{
442+
if(cur[0] == '\'' || cur[0] == '"'){
443+
KW(STR_PREFIX);
444+
}
445+
else {
446+
token(yylval.string);
447+
RET(TK_NAME);
448+
}
449+
}
450+
438451
// Tokens
439452
newline {
440453
if(parenlevel) { continue; }
@@ -763,6 +776,7 @@ std::string token2text(const int token)
763776

764777
T(KW_MATCH, "match")
765778
T(KW_CASE, "case")
779+
T(KW_STR_PREFIX, "string prefix")
766780

767781
default : {
768782
std::cout << "TOKEN: " << token << std::endl;

tests/errors/prefix_string_01.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def main():
2+
# python2 syntax should result in a syntax error
3+
print "Hello", "World"
4+
5+
main()

tests/errors/prefix_string_02.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from lpython import i32
2+
3+
# fix difference between lpython and cpython in prefix string grammar
4+
# Prefix should be attached to the quote without any whitespace.
5+
6+
def main():
7+
print(r "Hello World")
8+
9+
main()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"basename": "ast-prefix_string_01-cf221fd",
3+
"cmd": "lpython --show-ast --no-color {infile} -o {outfile}",
4+
"infile": "tests/errors/prefix_string_01.py",
5+
"infile_hash": "0d83c0e32a78023fccb343a4d3358071792265c1ae357176fe0912eb",
6+
"outfile": null,
7+
"outfile_hash": null,
8+
"stdout": null,
9+
"stdout_hash": null,
10+
"stderr": "ast-prefix_string_01-cf221fd.stderr",
11+
"stderr_hash": "b600057f41f59ba7fdebe3971bfea0eadca972747ccf70d575c1cdcd",
12+
"returncode": 1
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
syntax error: Token '"Hello"' (of type 'string') is unexpected here
2+
--> tests/errors/prefix_string_01.py:3:11
3+
|
4+
3 | print "Hello", "World"
5+
| ^^^^^^^
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"basename": "ast-prefix_string_02-3d530b2",
3+
"cmd": "lpython --show-ast --no-color {infile} -o {outfile}",
4+
"infile": "tests/errors/prefix_string_02.py",
5+
"infile_hash": "5d0c279ea735e60d5243a4b33100832dc1564917d6ef83c9b32705f9",
6+
"outfile": null,
7+
"outfile_hash": null,
8+
"stdout": null,
9+
"stdout_hash": null,
10+
"stderr": "ast-prefix_string_02-3d530b2.stderr",
11+
"stderr_hash": "cd72affed29823c0364d52bfb3ba0674d9d7950390b7cd6b04f7538b",
12+
"returncode": 1
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
syntax error: Token '"Hello World"' (of type 'string') is unexpected here
2+
--> tests/errors/prefix_string_02.py:7:13
3+
|
4+
7 | print(r "Hello World")
5+
| ^^^^^^^^^^^^^

tests/tests.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,14 @@ asr = true
12861286
filename = "errors/unsigned_04.py"
12871287
asr = true
12881288

1289+
[[test]]
1290+
filename = "errors/prefix_string_01.py"
1291+
ast = true
1292+
1293+
[[test]]
1294+
filename = "errors/prefix_string_02.py"
1295+
ast = true
1296+
12891297
# tests/runtime_errors
12901298
[[test]]
12911299
filename = "runtime_errors/test_list_01.py"

0 commit comments

Comments
 (0)