🐐 String indexing and slicing

This commit is contained in:
2026-04-21 23:07:40 +02:00
parent 378c28102c
commit 9003d49b20
5 changed files with 153 additions and 1 deletions

View File

@@ -639,6 +639,10 @@ error_tests = [
("I * \"hello\"", CentvrionError), # multiplication with string
("\"hello\" MINVS \"world\"", CentvrionError), # comparison with strings
("I[I]", CentvrionError), # indexing a non-array
('"SALVTE"[VII]', CentvrionError), # string index out of range
('"SALVTE"[NVLLVS]', CentvrionError), # string index with non-integer
('"SALVTE"[II VSQVE VII]', CentvrionError), # string slice out of range
('"SALVTE"[III VSQVE II]', CentvrionError), # string slice from > to
("DESIGNA x VT I\nDESIGNA x[I] VT II", CentvrionError), # index-assign to non-array
("SEMEN(I)", CentvrionError), # requires FORS module
('CVM FORS\nSEMEN("abc")', CentvrionError), # SEMEN requires integer seed
@@ -1583,6 +1587,88 @@ class TestArraySlice(unittest.TestCase):
run_test(self, source, nodes, value)
# --- String indexing ---
string_index_tests = [
# first character
('"SALVTE"[I]',
Program([], [ExpressionStatement(ArrayIndex(String("SALVTE"), Numeral("I")))]),
ValStr("S")),
# last character
('"SALVTE"[VI]',
Program([], [ExpressionStatement(ArrayIndex(String("SALVTE"), Numeral("VI")))]),
ValStr("E")),
# middle character
('"SALVTE"[III]',
Program([], [ExpressionStatement(ArrayIndex(String("SALVTE"), Numeral("III")))]),
ValStr("L")),
# string index via variable
('DESIGNA s VT "SALVTE"\ns[II]',
Program([], [
Designa(ID("s"), String("SALVTE")),
ExpressionStatement(ArrayIndex(ID("s"), Numeral("II"))),
]),
ValStr("A")),
# expression as index
('"SALVTE"[I + II]',
Program([], [ExpressionStatement(ArrayIndex(
String("SALVTE"),
BinOp(Numeral("I"), Numeral("II"), "SYMBOL_PLUS")))]),
ValStr("L")),
]
class TestStringIndex(unittest.TestCase):
@parameterized.expand(string_index_tests)
def test_string_index(self, source, nodes, value):
run_test(self, source, nodes, value)
# --- String slicing ---
string_slice_tests = [
# substring from middle
('"SALVTE"[II VSQVE IV]',
Program([], [ExpressionStatement(ArraySlice(
String("SALVTE"), Numeral("II"), Numeral("IV")))]),
ValStr("ALV")),
# full string slice
('"SALVTE"[I VSQVE VI]',
Program([], [ExpressionStatement(ArraySlice(
String("SALVTE"), Numeral("I"), Numeral("VI")))]),
ValStr("SALVTE")),
# single-char slice
('"SALVTE"[III VSQVE III]',
Program([], [ExpressionStatement(ArraySlice(
String("SALVTE"), Numeral("III"), Numeral("III")))]),
ValStr("L")),
# slice on variable
('DESIGNA s VT "SALVTE"\ns[II VSQVE IV]',
Program([], [
Designa(ID("s"), String("SALVTE")),
ExpressionStatement(ArraySlice(ID("s"), Numeral("II"), Numeral("IV"))),
]),
ValStr("ALV")),
# chaining: slice then index
('"SALVTE"[I VSQVE III][II]',
Program([], [ExpressionStatement(ArrayIndex(
ArraySlice(String("SALVTE"), Numeral("I"), Numeral("III")),
Numeral("II")))]),
ValStr("A")),
# expression as slice bounds
('"SALVTE"[I + I VSQVE II + II]',
Program([], [ExpressionStatement(ArraySlice(
String("SALVTE"),
BinOp(Numeral("I"), Numeral("I"), "SYMBOL_PLUS"),
BinOp(Numeral("II"), Numeral("II"), "SYMBOL_PLUS")))]),
ValStr("ALV")),
]
class TestStringSlice(unittest.TestCase):
@parameterized.expand(string_slice_tests)
def test_string_slice(self, source, nodes, value):
run_test(self, source, nodes, value)
# --- Comments ---
comment_tests = [