summaryrefslogtreecommitdiff
path: root/src/packrat-lexer-combinators.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/packrat-lexer-combinators.adb')
-rw-r--r--src/packrat-lexer-combinators.adb52
1 files changed, 40 insertions, 12 deletions
diff --git a/src/packrat-lexer-combinators.adb b/src/packrat-lexer-combinators.adb
index 6405efb..1090398 100644
--- a/src/packrat-lexer-combinators.adb
+++ b/src/packrat-lexer-combinators.adb
@@ -65,26 +65,23 @@ package body Packrat.Lexer.Combinators is
return Empty_Fail;
end if;
loop
+ exit when Position > Input'Last;
Temp := Param (Input, Position);
- exit when Temp.Status = Failure;
- if Temp.Status = Needs_More then
- Result.Status := Optional_More;
- exit;
- end if;
+ exit when Temp.Status = Failure or Temp.Status = Needs_More;
Result := Result.Join (Temp);
Counter := Counter + 1;
Position := Start + Result.Length;
- if Position > Input'Last then
- Result.Status := Optional_More;
- exit;
- end if;
end loop;
if Counter < Minimum then
- if Result.Status = Optional_More then
+ if Position > Input'Last or Temp.Status = Needs_More then
Result.Status := Needs_More;
else
Result.Status := Failure;
end if;
+ elsif Position > Input'Last or Temp.Status = Needs_More then
+ Result.Status := Optional_More;
+ else
+ Result.Status := Success;
end if;
return Result;
end Many;
@@ -93,9 +90,40 @@ package body Packrat.Lexer.Combinators is
function Many_Until
(Input : in Element_Array;
Start : in Positive)
- return Combinator_Result is
+ return Combinator_Result
+ is
+ Result : Combinator_Result := Create_Result (0, Success, Empty_Array);
+ Temp : Combinator_Result;
+ Position : Positive := Start;
+ Counter : Natural := 0;
begin
- return Empty_Fail;
+ if Start > Input'Last then
+ return Empty_Fail;
+ end if;
+ loop
+ exit when Position > Input'Last;
+ Temp := Param (Input, Position);
+ exit when Temp.Status = Failure or Temp.Status = Needs_More or Test (Input (Position));
+ Result := Result.Join (Temp);
+ Counter := Counter + 1;
+ Position := Start + Result.Length;
+ end loop;
+ if Counter < Minimum then
+ if Position > Input'Last or Temp.Status = Needs_More then
+ Result.Status := Needs_More;
+ else
+ Result.Status := Failure;
+ end if;
+ elsif Position > Input'Last then
+ Result.Status := Needs_More;
+ elsif Temp.Status = Needs_More and Test (Input (Position)) then
+ Result.Status := Optional_More;
+ elsif Test (Input (Position)) then
+ Result.Status := Success;
+ else
+ Result.Status := Failure;
+ end if;
+ return Result;
end Many_Until;