diff options
Diffstat (limited to 'src/packrat-lexer-combinators.adb')
-rw-r--r-- | src/packrat-lexer-combinators.adb | 206 |
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; |