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.adb206
1 files changed, 168 insertions, 38 deletions
diff --git a/src/packrat-lexer-combinators.adb b/src/packrat-lexer-combinators.adb
index 7dccede..6405efb 100644
--- a/src/packrat-lexer-combinators.adb
+++ b/src/packrat-lexer-combinators.adb
@@ -6,27 +6,87 @@ package body Packrat.Lexer.Combinators is
function Sequence
(Input : in Element_Array;
Start : in Positive)
- return Combinator_Result is
+ return Combinator_Result
+ is
+ Result : Combinator_Result := Create_Result (0, Success, Empty_Array);
+ Position : Positive := Start;
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ end if;
+ for C of Params loop
+ if Position > Input'Last then
+ Result.Status := Needs_More;
+ exit;
+ end if;
+ Result := Result.Join (C (Input, Position));
+ exit when Result.Status = Failure;
+ Position := Start + Result.Length;
+ end loop;
+ return Result;
end Sequence;
function Count
(Input : in Element_Array;
Start : in Positive)
- return Combinator_Result is
+ return Combinator_Result
+ is
+ Result : Combinator_Result := Create_Result (0, Success, Empty_Array);
+ Position : Positive := Start;
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ end if;
+ for I in Integer range 1 .. Number loop
+ if Position > Input'Last then
+ Result.Status := Needs_More;
+ exit;
+ end if;
+ Result := Result.Join (Param (Input, Position));
+ exit when Result.Status = Failure;
+ Position := Start + Result.Length;
+ end loop;
+ return Result;
end Count;
function Many
(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 Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ end if;
+ loop
+ Temp := Param (Input, Position);
+ exit when Temp.Status = Failure;
+ if Temp.Status = Needs_More then
+ Result.Status := Optional_More;
+ exit;
+ end if;
+ 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
+ Result.Status := Needs_More;
+ else
+ Result.Status := Failure;
+ end if;
+ end if;
+ return Result;
end Many;
@@ -35,7 +95,7 @@ package body Packrat.Lexer.Combinators is
Start : in Positive)
return Combinator_Result is
begin
- return Fail_Result;
+ return Empty_Fail;
end Many_Until;
@@ -47,7 +107,13 @@ package body Packrat.Lexer.Combinators is
Start : in Positive)
return Combinator_Result is
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ elsif Test (Input (Start)) then
+ return Create_Result (1, Success, (1 => Input (Start)));
+ else
+ return Empty_Fail;
+ end if;
end Satisfy;
@@ -56,7 +122,13 @@ package body Packrat.Lexer.Combinators is
Start : in Positive)
return Combinator_Result is
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ elsif Test (Change (Input (Start))) then
+ return Create_Result (1, Success, (1 => Input (Start)));
+ else
+ return Empty_Fail;
+ end if;
end Satisfy_With;
@@ -65,7 +137,13 @@ package body Packrat.Lexer.Combinators is
Start : in Positive)
return Combinator_Result is
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ elsif Input (Start) = Item then
+ return Create_Result (1, Success, (1 => Item));
+ else
+ return Empty_Fail;
+ end if;
end Match;
@@ -74,16 +152,40 @@ package body Packrat.Lexer.Combinators is
Start : in Positive)
return Combinator_Result is
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ elsif Change (Input (Start)) = Item then
+ return Create_Result (1, Success, (1 => Input (Start)));
+ else
+ return Empty_Fail;
+ end if;
end Match_With;
function Multimatch
(Input : in Element_Array;
Start : in Positive)
- return Combinator_Result is
+ return Combinator_Result
+ is
+ Current_Offset : Natural := 0;
begin
- return Fail_Result;
+ if Items'Length = 0 then
+ return Create_Result (0, Success, Empty_Array);
+ end if;
+
+ if Input'Last - Start + 1 <= 0 then
+ return Empty_Fail;
+ end if;
+
+ while Input (Start + Current_Offset) = Items (Items'First + Current_Offset) loop
+ if Items'First + Current_Offset = Items'Last then
+ return Create_Result (Current_Offset + 1, Success, Items);
+ elsif Start + Current_Offset = Input'Last then
+ return Create_Result (Current_Offset + 1, Needs_More, Input (Start .. Input'Last));
+ end if;
+ Current_Offset := Current_Offset + 1;
+ end loop;
+ return Create_Result (Current_Offset, Failure, Input (Start .. Start + Current_Offset - 1));
end Multimatch;
@@ -92,64 +194,92 @@ package body Packrat.Lexer.Combinators is
Start : in Positive)
return Combinator_Result is
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ elsif Start + Number - 1 > Input'Last then
+ return Create_Result (Input'Last - Start + 1, Needs_More, Input (Start .. Input'Last));
+ else
+ return Create_Result (Number, Success, Input (Start .. Start + Number - 1));
+ end if;
end Take;
function Take_While
(Input : in Element_Array;
Start : in Positive)
- return Combinator_Result is
+ return Combinator_Result
+ is
+ Finish : Positive := Start;
+ Status : Result_Status;
begin
- return Fail_Result;
+ if Start > Input'Last or else not Test (Input (Start)) then
+ return Empty_Fail;
+ end if;
+ while Finish <= Input'Last and then Test (Input (Finish)) loop
+ Finish := Finish + 1;
+ end loop;
+ if Finish > Input'Last then
+ Status := Optional_More;
+ else
+ Status := Success;
+ end if;
+ return Create_Result (Finish - Start, Status, Input (Start .. Finish - 1));
end Take_While;
function Take_Until
(Input : in Element_Array;
Start : in Positive)
- return Combinator_Result is
+ return Combinator_Result
+ is
+ Finish : Positive := Start;
+ Status : Result_Status;
begin
- return Fail_Result;
+ if Start > Input'Last or else Test (Input (Start)) then
+ return Empty_Fail;
+ end if;
+ while Finish <= Input'Last and then not Test (Input (Finish)) loop
+ Finish := Finish + 1;
+ end loop;
+ if Finish > Input'Last then
+ Status := Optional_More;
+ else
+ Status := Success;
+ end if;
+ return Create_Result (Finish - Start, Status, Input (Start .. Finish - 1));
end Take_Until;
- function Line_Start
- (Input : in Element_Array;
- Start : in Positive)
- return Combinator_Result is
- begin
- return Fail_Result;
- end Line_Start;
-
-
function Line_End
(Input : in Element_Array;
Start : in Positive)
return Combinator_Result is
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ elsif Input (Start) = EOL_Item then
+ return Create_Result (1, Success, (1 => EOL_Item));
+ else
+ return Empty_Fail;
+ end if;
end Line_End;
- function Input_Start
- (Input : in Element_Array;
- Start : in Positive)
- return Combinator_Result is
- begin
- return Fail_Result;
- end Input_Start;
-
-
function Input_End
(Input : in Element_Array;
Start : in Positive)
return Combinator_Result is
begin
- return Fail_Result;
+ if Start > Input'Last then
+ return Empty_Fail;
+ elsif Input (Start) = EOF_Item then
+ return Create_Result (1, Success, (1 => EOF_Item));
+ else
+ return Empty_Fail;
+ end if;
end Input_End;