perf(expression): improve string lexing & error messages
This commit is contained in:
parent
f4897391ec
commit
1e7eb20347
|
@ -99,18 +99,18 @@ class Scanner:
|
||||||
elif input[pos] == ",":
|
elif input[pos] == ",":
|
||||||
yield Token(TokenType.COMMA, ",", pos)
|
yield Token(TokenType.COMMA, ",", pos)
|
||||||
pos += 1
|
pos += 1
|
||||||
elif (quote_char := input[pos]) == "'" or input[pos] == '"':
|
elif (quote_char := input[pos]) in ("'", '"'):
|
||||||
quote_position = input[pos + 1 :].find(quote_char)
|
end_quote_pos = input.find(quote_char, pos + 1)
|
||||||
if quote_position == -1:
|
if end_quote_pos == -1:
|
||||||
raise ParseError(
|
raise ParseError(
|
||||||
pos + 1,
|
pos + 1,
|
||||||
f'closing quote "{quote_char}" is missing',
|
f'closing quote "{quote_char}" is missing',
|
||||||
)
|
)
|
||||||
value = input[pos : pos + 2 + quote_position]
|
value = input[pos : end_quote_pos + 1]
|
||||||
if "\\" in value:
|
if (backslash_pos := input.find("\\")) != -1:
|
||||||
raise ParseError(
|
raise ParseError(
|
||||||
pos + 1,
|
backslash_pos + 1,
|
||||||
"escaping not supported in marker expression",
|
r'escaping with "\" not supported in marker expression',
|
||||||
)
|
)
|
||||||
yield Token(TokenType.STRING, value, pos)
|
yield Token(TokenType.STRING, value, pos)
|
||||||
pos += len(value)
|
pos += len(value)
|
||||||
|
@ -218,10 +218,15 @@ BUILTIN_MATCHERS = {"True": True, "False": False, "None": None}
|
||||||
|
|
||||||
def single_kwarg(s: Scanner) -> ast.keyword:
|
def single_kwarg(s: Scanner) -> ast.keyword:
|
||||||
keyword_name = s.accept(TokenType.IDENT, reject=True)
|
keyword_name = s.accept(TokenType.IDENT, reject=True)
|
||||||
if not keyword_name.value.isidentifier() or keyword.iskeyword(keyword_name.value):
|
if not keyword_name.value.isidentifier():
|
||||||
raise ParseError(
|
raise ParseError(
|
||||||
keyword_name.pos + 1,
|
keyword_name.pos + 1,
|
||||||
f'unexpected character/s "{keyword_name.value}"',
|
f"not a valid python identifier {keyword_name.value}",
|
||||||
|
)
|
||||||
|
if keyword.iskeyword(keyword_name.value):
|
||||||
|
raise ParseError(
|
||||||
|
keyword_name.pos + 1,
|
||||||
|
f"unexpected reserved python keyword `{keyword_name.value}`",
|
||||||
)
|
)
|
||||||
s.accept(TokenType.EQUAL, reject=True)
|
s.accept(TokenType.EQUAL, reject=True)
|
||||||
|
|
||||||
|
|
|
@ -207,25 +207,29 @@ def test_invalid_idents(ident: str) -> None:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"expr, expected_error_msg",
|
"expr, expected_error_msg",
|
||||||
(
|
(
|
||||||
("mark(1=2)", 'unexpected character/s "1"'),
|
("mark(True=False)", "unexpected reserved python keyword `True`"),
|
||||||
("mark(/=2)", 'unexpected character/s "/"'),
|
("mark(def=False)", "unexpected reserved python keyword `def`"),
|
||||||
("mark(True=False)", 'unexpected character/s "True"'),
|
("mark(class=False)", "unexpected reserved python keyword `class`"),
|
||||||
("mark(def=False)", 'unexpected character/s "def"'),
|
("mark(if=False)", "unexpected reserved python keyword `if`"),
|
||||||
("mark(class=False)", 'unexpected character/s "class"'),
|
("mark(else=False)", "unexpected reserved python keyword `else`"),
|
||||||
("mark(if=False)", 'unexpected character/s "if"'),
|
("mark(valid=False, def=1)", "unexpected reserved python keyword `def`"),
|
||||||
("mark(else=False)", 'unexpected character/s "else"'),
|
("mark(1)", "not a valid python identifier 1"),
|
||||||
("mark(1)", 'unexpected character/s "1"'),
|
("mark(var:=False", "not a valid python identifier var:"),
|
||||||
("mark(var:=False", 'unexpected character/s "var:"'),
|
("mark(1=2)", "not a valid python identifier 1"),
|
||||||
("mark(valid=False, def=1)", 'unexpected character/s "def"'),
|
("mark(/=2)", "not a valid python identifier /"),
|
||||||
("mark(var==", "expected identifier; got ="),
|
("mark(var==", "expected identifier; got ="),
|
||||||
|
("mark(var)", "expected =; got right parenthesis"),
|
||||||
("mark(var=none)", 'unexpected character/s "none"'),
|
("mark(var=none)", 'unexpected character/s "none"'),
|
||||||
("mark(var=1.1)", 'unexpected character/s "1.1"'),
|
("mark(var=1.1)", 'unexpected character/s "1.1"'),
|
||||||
("mark(var)", "expected =; got right parenthesis"),
|
|
||||||
("mark(var=')", """closing quote "'" is missing"""),
|
("mark(var=')", """closing quote "'" is missing"""),
|
||||||
('mark(var=")', 'closing quote """ is missing'),
|
('mark(var=")', 'closing quote """ is missing'),
|
||||||
("""mark(var="')""", 'closing quote """ is missing'),
|
("""mark(var="')""", 'closing quote """ is missing'),
|
||||||
("""mark(var='")""", """closing quote "'" is missing"""),
|
("""mark(var='")""", """closing quote "'" is missing"""),
|
||||||
(r"mark(var='\hugo')", "escaping not supported in marker expression"),
|
(
|
||||||
|
r"mark(var='\hugo')",
|
||||||
|
r'escaping with "\\" not supported in marker expression',
|
||||||
|
),
|
||||||
|
("mark(empty_list=[])", r'unexpected character/s "\[\]"'),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_invalid_kwarg_name_or_value( # TODO: move to `test_syntax_errors` ?
|
def test_invalid_kwarg_name_or_value( # TODO: move to `test_syntax_errors` ?
|
||||||
|
|
Loading…
Reference in New Issue