multiple lists work :o

This commit is contained in:
Jesse Bannon 2023-11-07 01:00:59 -08:00
parent 870b3ee018
commit ec62c7fe67
6 changed files with 54 additions and 14 deletions

View file

@ -1,9 +1,10 @@
from typing import Optional
from ytdl_sub.script.functions.array_functions import ArrayFunctions
from ytdl_sub.script.functions.numeric_functions import NumericFunctions
from ytdl_sub.script.functions.special_functions import SpecialFunctions
from ytdl_sub.script.functions.string_functions import StringFunctions
class Functions(StringFunctions, NumericFunctions, SpecialFunctions):
class Functions(StringFunctions, NumericFunctions, SpecialFunctions, ArrayFunctions):
pass

View file

@ -0,0 +1,14 @@
from typing import List
from ytdl_sub.script.types.resolvable import Array
from ytdl_sub.script.types.resolvable import Resolvable
class ArrayFunctions:
@staticmethod
def extend(*arrays: Array) -> Array:
output: List[Resolvable] = []
for array in arrays:
output.extend(array.value)
return Array(output)

View file

@ -4,6 +4,7 @@ from typing import Optional
from ytdl_sub.script.syntax_tree import SyntaxTree
from ytdl_sub.script.types.function import ArgumentType
from ytdl_sub.script.types.function import Function
from ytdl_sub.script.types.resolvable import Array
from ytdl_sub.script.types.resolvable import Boolean
from ytdl_sub.script.types.resolvable import Float
from ytdl_sub.script.types.resolvable import Integer
@ -48,7 +49,7 @@ class _Parser:
if ch.isspace() and not var_name:
self._pos += 1
continue
if ch in ["}", ",", ")"] or ch.isspace():
if ch in ["}", ",", ")", "]"] or ch.isspace():
break
is_lower = ch.isascii() and ch.islower()
@ -115,6 +116,9 @@ class _Parser:
return Boolean(value=False)
if self._read(increment_pos=False) in ["'", '"']:
return self._parse_string()
if self._read(increment_pos=False) == "[":
self._pos += 1
return self._parse_array()
if self._read(increment_pos=False).isascii() and self._read(increment_pos=False).islower():
return self._parse_variable()
raise StringFormattingException(
@ -122,7 +126,7 @@ class _Parser:
"string, boolean, or variable without brackets"
)
def _parse_function_args(self) -> List[ArgumentType]:
def _parse_args(self, breaking_char: str = ")") -> List[ArgumentType]:
"""
Begin parsing function args after the first ``(``, i.e. ``function_name(``
"""
@ -131,7 +135,7 @@ class _Parser:
arguments: List[ArgumentType] = []
while ch := self._read(increment_pos=False):
if ch == ")":
if ch == breaking_char:
break
if ch.isspace():
@ -162,7 +166,22 @@ class _Parser:
if ch != "(":
function_name += ch
else:
function_args = self._parse_function_args()
function_args = self._parse_args()
raise StringFormattingException("Invalid function")
def _parse_array(self) -> Array:
"""
Begin parsing an array after reading the first ``[``
"""
function_args: List[String | Variable | "Function"] = []
while ch := self._read(increment_pos=False):
if ch == "]":
self._pos += 1
return Array(value=function_args)
else:
function_args = self._parse_args(breaking_char="]")
raise StringFormattingException("Invalid function")
@ -193,6 +212,9 @@ class _Parser:
if ch1 == "%":
self._pos += 1
self._ast.append(self._parse_function())
elif ch1 == "[":
self._pos += 1
self._ast.append(self._parse_array())
else:
self._ast.append(self._parse_variable())
else:

View file

@ -15,6 +15,7 @@ from typing import final
from typing import get_origin
from ytdl_sub.script.functions import Functions
from ytdl_sub.script.types.resolvable import Array
from ytdl_sub.script.types.resolvable import Boolean
from ytdl_sub.script.types.resolvable import Float
from ytdl_sub.script.types.resolvable import Integer
@ -26,7 +27,7 @@ from ytdl_sub.script.types.resolvable import String
from ytdl_sub.script.types.variable import Variable
from ytdl_sub.utils.exceptions import StringFormattingException
ArgumentType = Union[Integer, Float, String, Boolean, Variable, "Function"]
ArgumentType = Union[Integer, Float, String, Boolean, Variable, "Function", Array]
@dataclass(frozen=True)

View file

@ -61,13 +61,8 @@ class String(ResolvableT[str]):
@dataclass(frozen=True)
class _List(Resolvable, Generic[T], ABC):
value: List[T]
class Array(Resolvable):
value: List[Resolvable]
def __str__(self) -> str:
return f"[{', '.join([str(val) for val in self.value])}]"
@dataclass(frozen=True)
class StringList(_List[String]):
pass
return f"[{', '.join([val.value for val in self.value])}]"

View file

@ -28,6 +28,13 @@ class TestParser:
]
)
def test_array(self):
parsed = parse("hello {['elem1', 'elem2']}")
parsed_empty = parse("hello {[]}")
parsed_with_var = parse("hello {['elem1', variable_name]}")
parsed_extend = parse("hi {%extend(['elem1', 'elem2'], ['elem3'], [], ['elem4'])}")
assert False
def test_conditional(self):
parsed = parse("hello {%if(True, 'hi', 3.4)}")
assert parsed == SyntaxTree(