@@ -347,6 +347,73 @@ def test_at_most(self):
347347 self .assertEqual (ab .at_most (2 ).parse ("abab" ), ["ab" , "ab" ])
348348 self .assertRaises (ParseError , ab .at_most (2 ).parse , "ababab" )
349349
350+ def test_until (self ):
351+
352+ until = string ("s" ).until (string ("x" ))
353+
354+ s = "ssssx"
355+ self .assertEqual (until .parse_partial (s ), (4 * ["s" ], "x" ))
356+ self .assertEqual (seq (until , string ("x" )).parse (s ), [4 * ["s" ], "x" ])
357+ self .assertEqual (until .then (string ("x" )).parse (s ), "x" )
358+
359+ s = "ssssxy"
360+ self .assertEqual (until .parse_partial (s ), (4 * ["s" ], "xy" ))
361+ self .assertEqual (seq (until , string ("x" )).parse_partial (s ), ([4 * ["s" ], "x" ], "y" ))
362+ self .assertEqual (until .then (string ("x" )).parse_partial (s ), ("x" , "y" ))
363+
364+ self .assertRaises (ParseError , until .parse , "ssssy" )
365+ self .assertRaises (ParseError , until .parse , "xssssxy" )
366+
367+ self .assertEqual (until .parse_partial ("xxx" ), ([], "xxx" ))
368+
369+ until = regex ("." ).until (string ("x" ))
370+ self .assertEqual (until .parse_partial ("xxxx" ), ([], "xxxx" ))
371+
372+ def test_until_with_consume_other (self ):
373+
374+ until = string ("s" ).until (string ("x" ), consume_other = True )
375+
376+ self .assertEqual (until .parse ("ssssx" ), 4 * ["s" ] + ["x" ])
377+ self .assertEqual (until .parse_partial ("ssssxy" ), (4 * ["s" ] + ["x" ], "y" ))
378+
379+ self .assertEqual (until .parse_partial ("xxx" ), (["x" ], "xx" ))
380+
381+ self .assertRaises (ParseError , until .parse , "ssssy" )
382+ self .assertRaises (ParseError , until .parse , "xssssxy" )
383+
384+ def test_until_with_min (self ):
385+
386+ until = string ("s" ).until (string ("x" ), min = 3 )
387+
388+ self .assertEqual (until .parse_partial ("sssx" ), (3 * ["s" ], "x" ))
389+ self .assertEqual (until .parse_partial ("sssssx" ), (5 * ["s" ], "x" ))
390+
391+ self .assertRaises (ParseError , until .parse_partial , "ssx" )
392+
393+ def test_until_with_max (self ):
394+
395+ # until with max
396+ until = string ("s" ).until (string ("x" ), max = 3 )
397+
398+ self .assertEqual (until .parse_partial ("ssx" ), (2 * ["s" ], "x" ))
399+ self .assertEqual (until .parse_partial ("sssx" ), (3 * ["s" ], "x" ))
400+
401+ self .assertRaises (ParseError , until .parse_partial , "ssssx" )
402+
403+ def test_until_with_min_max (self ):
404+
405+ until = string ("s" ).until (string ("x" ), min = 3 , max = 5 )
406+
407+ self .assertEqual (until .parse_partial ("sssx" ), (3 * ["s" ], "x" ))
408+ self .assertEqual (until .parse_partial ("sssssx" ), (5 * ["s" ], "x" ))
409+
410+ with self .assertRaises (ParseError ) as cm :
411+ until .parse_partial ("ssx" )
412+ assert cm .exception .args [0 ] == frozenset ({"at least 3 items; got 2 item(s)" })
413+ with self .assertRaises (ParseError ) as cm :
414+ until .parse_partial ("ssssssx" )
415+ assert cm .exception .args [0 ] == frozenset ({"at most 5 items" })
416+
350417 def test_optional (self ):
351418 p = string ("a" ).optional ()
352419 self .assertEqual (p .parse ("a" ), "a" )
0 commit comments