no more escaping strings, triple quote
This commit is contained in:
parent
94e028536f
commit
70876dc123
3 changed files with 33 additions and 22 deletions
|
|
@ -104,10 +104,18 @@ def _is_numeric_start(char: str) -> bool:
|
||||||
return char.isnumeric() or char == "-"
|
return char.isnumeric() or char == "-"
|
||||||
|
|
||||||
|
|
||||||
def _is_string_start(char: str) -> bool:
|
def _is_string_start_single_char(char: Optional[str]) -> bool:
|
||||||
return char in ["'", '"']
|
return char in ["'", '"']
|
||||||
|
|
||||||
|
|
||||||
|
def _is_string_start_multi_char(string: Optional[str]) -> bool:
|
||||||
|
return string in ["'''", '"""']
|
||||||
|
|
||||||
|
|
||||||
|
def _is_null(string: Optional[str]) -> bool:
|
||||||
|
return string and string.lower() == "null"
|
||||||
|
|
||||||
|
|
||||||
def _is_breakable(char: str) -> bool:
|
def _is_breakable(char: str) -> bool:
|
||||||
return char in ["}", ",", ")", "]"] or char.isspace()
|
return char in ["}", ",", ")", "]"] or char.isspace()
|
||||||
|
|
||||||
|
|
@ -120,10 +128,6 @@ def _is_boolean_false(string: Optional[str]) -> bool:
|
||||||
return string and string.lower() == "false"
|
return string and string.lower() == "false"
|
||||||
|
|
||||||
|
|
||||||
def _is_null(string: Optional[str]) -> bool:
|
|
||||||
return string and string.lower() == "null"
|
|
||||||
|
|
||||||
|
|
||||||
def _is_custom_function_argument_start(char: str) -> bool:
|
def _is_custom_function_argument_start(char: str) -> bool:
|
||||||
return char == "$"
|
return char == "$"
|
||||||
|
|
||||||
|
|
@ -273,28 +277,25 @@ class _Parser:
|
||||||
|
|
||||||
return Float(value=numeric_float)
|
return Float(value=numeric_float)
|
||||||
|
|
||||||
def _parse_string(self) -> String:
|
def _parse_string(self, str_open_token: str) -> String:
|
||||||
"""
|
"""
|
||||||
Begin parsing a string, including the quotation value
|
Begin parsing a string, including the quotation value
|
||||||
"""
|
"""
|
||||||
self._set_highlight_position()
|
self._set_highlight_position()
|
||||||
string_value = ""
|
string_value = ""
|
||||||
open_quotation_char = self._read()
|
|
||||||
|
|
||||||
if not _is_string_start(open_quotation_char):
|
if not _is_string_start_single_char(str_open_token) and not _is_string_start_multi_char(
|
||||||
|
str_open_token
|
||||||
|
):
|
||||||
raise UNREACHABLE
|
raise UNREACHABLE
|
||||||
|
|
||||||
is_escaped = False
|
while ch := self._read(increment_pos=False):
|
||||||
while ch := self._read():
|
if self._read(increment_pos=False, length=len(str_open_token)) == str_open_token:
|
||||||
if ch == open_quotation_char and not is_escaped:
|
self._pos += len(str_open_token)
|
||||||
return String(value=string_value)
|
return String(value=string_value)
|
||||||
|
|
||||||
if ch == "\\" and not is_escaped:
|
self._pos += 1
|
||||||
is_escaped = True
|
|
||||||
continue
|
|
||||||
|
|
||||||
string_value += ch
|
string_value += ch
|
||||||
is_escaped = False
|
|
||||||
|
|
||||||
raise STRINGS_NOT_CLOSED
|
raise STRINGS_NOT_CLOSED
|
||||||
|
|
||||||
|
|
@ -313,8 +314,12 @@ class _Parser:
|
||||||
if _is_null(self._read(increment_pos=False, length=4)):
|
if _is_null(self._read(increment_pos=False, length=4)):
|
||||||
self._pos += 4
|
self._pos += 4
|
||||||
return String(value="")
|
return String(value="")
|
||||||
if _is_string_start(self._read(increment_pos=False)):
|
if _is_string_start_multi_char(str_open_token := self._read(increment_pos=False, length=3)):
|
||||||
return self._parse_string()
|
self._pos += 3
|
||||||
|
return self._parse_string(str_open_token)
|
||||||
|
if _is_string_start_single_char(str_open_token := self._read(increment_pos=False)):
|
||||||
|
self._pos += 1
|
||||||
|
return self._parse_string(str_open_token)
|
||||||
if self._read(increment_pos=False) == "[":
|
if self._read(increment_pos=False) == "[":
|
||||||
self._pos += 1
|
self._pos += 1
|
||||||
return self._parse_array()
|
return self._parse_array()
|
||||||
|
|
@ -535,7 +540,11 @@ class _Parser:
|
||||||
self._ast.append(self._parse_variable())
|
self._ast.append(self._parse_variable())
|
||||||
elif _is_numeric_start(ch1):
|
elif _is_numeric_start(ch1):
|
||||||
raise NUMERICS_ONLY_ARGS
|
raise NUMERICS_ONLY_ARGS
|
||||||
elif _is_string_start(ch1) or _is_null(self._read(increment_pos=False, length=4)):
|
elif (
|
||||||
|
_is_string_start_single_char(ch1)
|
||||||
|
or _is_string_start_multi_char(self._read(increment_pos=False, length=3))
|
||||||
|
or _is_null(self._read(increment_pos=False, length=4))
|
||||||
|
):
|
||||||
raise STRINGS_ONLY_ARGS
|
raise STRINGS_ONLY_ARGS
|
||||||
elif _is_boolean_true(
|
elif _is_boolean_true(
|
||||||
self._read(increment_pos=False, length=4)
|
self._read(increment_pos=False, length=4)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import pytest
|
import pytest
|
||||||
from unit.script.conftest import single_variable_output
|
from unit.script.conftest import single_variable_output
|
||||||
|
|
||||||
|
|
||||||
class TestNumericFunctions:
|
class TestNumericFunctions:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"values, expected_output",
|
"values, expected_output",
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ class TestString:
|
||||||
[
|
[
|
||||||
("{%string('')}", ""),
|
("{%string('')}", ""),
|
||||||
('{%string("")}', ""),
|
('{%string("")}', ""),
|
||||||
|
('{%string("\\")}', "\\"),
|
||||||
("{%string('323')}", "323"),
|
("{%string('323')}", "323"),
|
||||||
('{%string( "4253" )}', "4253"),
|
('{%string( "4253" )}', "4253"),
|
||||||
('{%string("hi")}', "hi"),
|
('{%string("hi")}', "hi"),
|
||||||
|
|
@ -41,9 +42,9 @@ class TestString:
|
||||||
("{%string('in function')} out of function", "in function out of function"),
|
("{%string('in function')} out of function", "in function out of function"),
|
||||||
("{%string('supports \" in string')}", 'supports " in string'),
|
("{%string('supports \" in string')}", 'supports " in string'),
|
||||||
('{%string("supports \' in string")}', "supports ' in string"),
|
('{%string("supports \' in string")}', "supports ' in string"),
|
||||||
('{%string("\\" in string with open \\"")}', '" in string with open "'),
|
("{%string('backslash \\\\')}", "backslash \\\\"),
|
||||||
("{%string('\\' in string with open \\'')}", "' in string with open '"),
|
("{%string('''triple quote with \" ' \\''')}", "triple quote with \" ' \\"),
|
||||||
("{%string('backslash \\\\')}", "backslash \\"),
|
('{%string("""triple quote with " \' \\""")}', "triple quote with \" ' \\"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_string(self, string: str, expected_string: str):
|
def test_string(self, string: str, expected_string: str):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue