packages feed

gll 0.3.0.7 → 0.3.0.9

raw patch · 10 files changed

+359/−170 lines, 10 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- GLL.Combinators.Interface: instance GLL.Combinators.Interface.HasAlts GLL.Combinators.Interface.AltExpr
- GLL.Combinators.Interface: instance GLL.Combinators.Interface.HasAlts GLL.Combinators.Interface.AltExprs
- GLL.Combinators.Interface: instance GLL.Combinators.Interface.HasAlts GLL.Combinators.Interface.SymbExpr
- GLL.Combinators.Interface: instance GLL.Combinators.Interface.IsAltExpr GLL.Combinators.Interface.AltExpr
- GLL.Combinators.Interface: instance GLL.Combinators.Interface.IsAltExpr GLL.Combinators.Interface.AltExprs
- GLL.Combinators.Interface: instance GLL.Combinators.Interface.IsAltExpr GLL.Combinators.Interface.SymbExpr
- GLL.Combinators.Interface: instance GLL.Combinators.Interface.IsSymbExpr GLL.Combinators.Interface.AltExpr
- GLL.Combinators.Interface: instance GLL.Combinators.Interface.IsSymbExpr GLL.Combinators.Interface.AltExprs
- GLL.Combinators.Interface: instance GLL.Combinators.Interface.IsSymbExpr GLL.Combinators.Interface.SymbExpr
+ GLL.Combinators.Interface: (**>>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t b
+ GLL.Combinators.Interface: (<**>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t a
+ GLL.Combinators.Interface: (<**>>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t (a -> b) -> s t a -> AltExpr t b
+ GLL.Combinators.Interface: (<:=) :: (Ord t, Show t, HasAlts b) => String -> b t a -> SymbExpr t a
+ GLL.Combinators.Interface: (<<**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t b
+ GLL.Combinators.Interface: (<<<**) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t a
+ GLL.Combinators.Interface: (<<<**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t (a -> b) -> s t a -> AltExpr t b
+ GLL.Combinators.Interface: CharLit :: (Maybe Char) -> Token
+ GLL.Combinators.Interface: angles :: BNF Token b -> BNF Token b
+ GLL.Combinators.Interface: braces :: BNF Token b -> BNF Token b
+ GLL.Combinators.Interface: brackets :: BNF Token b -> BNF Token b
+ GLL.Combinators.Interface: char_lit :: SubsumesToken t => SymbExpr t Char
+ GLL.Combinators.Interface: manySepBy2 :: (Ord t, Show t, IsAltExpr s2, IsSymbExpr s, IsSymbExpr s2) => s t a -> s2 t b -> BNF t [a]
+ GLL.Combinators.Interface: maximumPivot :: CombinatorOption
+ GLL.Combinators.Interface: maximumPivotAtNt :: CombinatorOption
+ GLL.Combinators.Interface: multipleSepBy2 :: (Ord t, Show t, IsAltExpr s2, IsSymbExpr s, IsSymbExpr s2) => s t a -> s2 t b -> BNF t [a]
+ GLL.Combinators.Interface: parens :: BNF Token b -> BNF Token b
+ GLL.Combinators.Interface: someSepBy2 :: (Ord t, Show t, IsAltExpr s2, IsSymbExpr s, IsSymbExpr s2) => s t a -> s2 t b -> BNF t [a]
+ GLL.Combinators.Interface: unlex :: Parseable a => a -> String
+ GLL.Combinators.Interface: unlexToken :: Token -> String
+ GLL.Combinators.Interface: unlexTokens :: [Token] -> String
+ GLL.Combinators.Interface: within :: BNF Token a -> BNF Token b -> BNF Token c -> BNF Token b
+ GLL.Parser: unlex :: Parseable a => a -> String
- GLL.Combinators.Interface: class (Ord a, Eq a, Show a) => Parseable a
+ GLL.Combinators.Interface: class (Ord a, Eq a, Show a) => Parseable a where unlex = show
- GLL.Parser: class (Ord a, Eq a, Show a) => Parseable a
+ GLL.Parser: class (Ord a, Eq a, Show a) => Parseable a where unlex = show

Files

changelog.txt view
@@ -1,23 +1,11 @@-0.3.0.1 -> 0.3.0.2-    + smart constructors for creating Grammars. To be used instead of constructors.-0.3.0.2 -> 0.3.0.3-    + SubsumesToken class for making Token a subtype of a custom Parseable type.-        The terminal parsers id_lit, int_lit, etc. can be used directly.-    + Additional constructor in 'Token' for alternative identifiers.-    - Method 'matches' of class 'Parseable' no longer has a default definition-        (default was (==)).-0.3.0.3 -> 0.3.0.4-    + introduced lassoc, rassoc and assoc for associativity based -        local disambiguation-    + renamed some to many1 and let many and many1 implement shortest-match,-        hence, if there is ambiguity the list with the maximum size is chosen.-    + introduced some and some1 that are the same as many/many1 except-        that they implement longest-match (resulting in minimum sized list)-    + introduced multiple and multiple1 that are as above but implementing-        no disambiguation (possibly useful for debuggin)-    + introduced manySepBy(1), someSepBy(1) and multipleSepBy(1)-0.3.0.4 -> 0.3.0.6-    + added missing string literal token to predefined lexer-    + added user-defined tokens to predefined lexer (given as a list)-0.3.0.6 -> 0.3.0.7-    + relaxed constraint on base +0.3.0.7 -> 0.3.0.8+  + export maximumPivots and maximumPivotAtNt+0.3.0.8 -> 0.3.0.9+  + include bit of the input string when showing an error message (without whitespace)+  + exporting <multiple/some/many>SepBy2+  + exporting within, parens, braces, brackets, angles, quotes and dquotes+  + added character literals to Token type+  + exporting <:=+  + <<<**> and <**>>> for shortest and longest match, respectively+    defined some/many and variants using <**>>> and <<<**>+    disambiguation remains very experimental 
gll.cabal view
@@ -3,7 +3,7 @@  -- The name of the package. name:                gll-version:             0.3.0.7+version:             0.3.0.9 synopsis:            GLL parser with simple combinator interface  license:             BSD3 license-file:        LICENSE@@ -59,6 +59,7 @@                         , GLL.Types.Grammar                         , GLL.Combinators.Visit.Grammar                         , GLL.Combinators.Visit.Sem+                        , GLL.Combinators.Visit.Join     extensions      : TypeOperators, FlexibleInstances, ScopedTypeVariables, TypeSynonymInstances     ghc-options:         -fwarn-incomplete-patterns -fwarn-monomorphism-restriction -fwarn-unused-imports 
src/GLL/Combinators/Interface.hs view
@@ -182,7 +182,7 @@     -- * Elementary parsers     term_parser, satisfy,     -- ** Elementary parsers using the 'Token' datatype -    keychar, keyword, int_lit, bool_lit, string_lit, alt_id_lit, id_lit, token,+    keychar, keyword, int_lit, bool_lit, char_lit, string_lit, alt_id_lit, id_lit, token,     -- ** Elementary character-level parsers     char,      -- * Elementary combinators@@ -198,14 +198,15 @@     -- ** Grammar (combinator expression) types     BNF, SymbExpr, AltExpr, AltExprs,     -- ** Parseable token types -    Token(..), Parseable(..), SubsumesToken(..), +    Token(..), Parseable(..), SubsumesToken(..), unlexTokens, unlexToken,       -- * Running a parser      parse,      -- **  Running a parser with options     parseWithOptions,     -- *** Possible options     CombinatorOptions, CombinatorOption, -             GLL.Combinators.Options.maximumErrors, throwErrors,+             GLL.Combinators.Options.maximumErrors, throwErrors, +             maximumPivot, maximumPivotAtNt,     -- **** Parser options     fullSPPF, allNodes, packedNodesOnly, strictBinarisation,     -- *** Running a parser with options and explicit failure@@ -222,10 +223,13 @@     (<$$), (**>), (<**),     -- *** EBNF patterns     optional, multiple, multiple1, multipleSepBy, multipleSepBy1,+      multipleSepBy2, within, parens, braces, brackets, angles,      -- *** Disambiguation  -            (<::=),-            lassoc, rassoc, assoc,many, many1, some, some1, -            manySepBy, manySepBy1, someSepBy, someSepBy1, +            (<:=), (<::=),(<<<**>), (<**>>>), (<<**>), (<<<**), (**>>>), (<**>>),+            rassoc, lassoc, assoc,+            many, many1, some, some1, +            manySepBy, manySepBy1, manySepBy2, +              someSepBy, someSepBy1,someSepBy2,     -- * Lifting     HasAlts(..), IsSymbExpr(..), IsAltExpr(..),      -- * Memoisation@@ -233,17 +237,15 @@     ) where  import GLL.Combinators.Options-import GLL.Combinators.Visit.Sem-import GLL.Combinators.Visit.Grammar+import GLL.Combinators.Visit.Join import GLL.Combinators.Memoisation import GLL.Combinators.Lexer import GLL.Types.Abstract import GLL.Parser hiding (parse, parseWithOptions, Options, Option, runOptions) import qualified GLL.Parser as GLL +import Control.Compose (OO(..)) import Control.Arrow-import Control.Compose (OO(..),unOO)-import Data.List (intercalate) import qualified Data.Array as A import qualified Data.IntMap as IM import qualified Data.Map as M@@ -251,24 +253,6 @@ import Data.IORef  import System.IO.Unsafe --- | A combinator expression representing a symbol.--- A 'SymbExpr' either represents a terminal or a nonterminal.--- In the latter case it is constructed with (a variant of) '<:=>' and --- adds a rule to the grammar of which the represented symbol is the --- left-hand side.-data SymbExpr t a = SymbExpr (Symbol t, Grammar_Expr t, Sem_Symb t a)--- | A combinator expression representing a BNF-grammar. The terminals of--- the grammar are of type 't'. When used to parse, the expression yields--- semantic results of type 'a'. -type BNF t a = SymbExpr t a--- | --- A combinator expression representing an alternative: --- the right-hand side of a production.-data AltExpr t a = AltExpr ([Symbol t], Grammar_Expr t, Sem_Alt t a)---- | A list of alternatives represents the right-hand side of a rule.-type AltExprs = OO [] AltExpr- parse' :: (Show t, Parseable t, IsSymbExpr s) => ParseOptions ->              PCOptions -> s t a -> [t] -> (Grammar t, ParseResult t, Either String [a]) parse' popts opts p' input =  @@ -347,26 +331,14 @@ (<::=>) :: (Show t, Ord t, HasAlts b) => String -> b t a -> SymbExpr t a  x <::=> altPs = mkNtRule True False x altPs -mkNtRule :: (Show t, Ord t, HasAlts b) => Bool -> Bool -> String -> b t a -> SymbExpr t a-mkNtRule use_ctx left_biased x' altPs' =-    let vas1 = map (\(AltExpr (f,_,_)) -> f) altPs -        vas2 = map (\(AltExpr (_,s,_)) -> s) altPs-        vas3 = map (\(AltExpr (_,_,t)) -> t) altPs-        alts  = map (Prod x) vas1    -        altPs = altsOf altPs'-        x     = pack x'-    in SymbExpr (Nt x, grammar_nterm x alts vas2, sem_nterm use_ctx left_biased x alts vas3)- infixl 4 <$$> -- | -- Form an 'AltExpr' by mapping some semantic action overy the result -- of the second argument. (<$$>) :: (Show t, Ord t, IsSymbExpr s) => (a -> b) -> s t a -> AltExpr t b-f <$$> p' = -    let SymbExpr (vpa1,vpa2,vpa3) = mkRule p' in AltExpr-          ([vpa1],grammar_apply vpa2, sem_apply f vpa3) +f <$$> p' = join_apply f p' -infixl 4 <**>+infixl 4 <**>,<<<**>,<**>>> -- |  -- Add a 'SymbExpr' to the right-hand side represented by an 'AltExpr' -- creating a new 'AltExpr'. @@ -374,11 +346,19 @@ -- as a cross-product.  (<**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) =>              i t (a -> b) -> s t a -> AltExpr t b-pl' <**> pr' = -  let AltExpr (vimp1,vimp2,vimp3) = toAlt pl'-      SymbExpr (vpa1,vpa2,vpa3)  = mkRule pr' in AltExpr-  (vimp1++[vpa1], grammar_seq vimp2 vpa2, sem_seq vimp3 vpa3)+pl' <**> pr' = join_seq [] pl' pr' +-- | Variant of '<**>' that applies longest match on the left operand.+(<**>>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => +            i t (a -> b) -> s t a -> AltExpr t b+pl' <**>>> pr' = join_seq [maximumPivot] pl' pr'++-- | Variant of '<**>' that applies shortest match on the left operand.+(<<<**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => +            i t (a -> b) -> s t a -> AltExpr t b+pl' <<<**> pr' = join_seq [minimumPivot] pl' pr'++ infixr 3 <||> -- | -- Add an 'AltExpr' to a list of 'AltExpr'@@ -464,6 +444,13 @@  where  unwrap (Just (BoolLit (Just b)))  = b         unwrap _ = error "bool_lit: downcast, or token without lexeme" +-- | Parse a single Character literal, using a 'SubsumesToken' type.+-- Returns the lexeme interpreted as a Character literal.+char_lit :: SubsumesToken t => SymbExpr t Char+char_lit  = term_parser (upcast (CharLit Nothing)) (unwrap . downcast)+ where  unwrap (Just (CharLit (Just s))) = s+        unwrap _ = error "char_lit: downcast, or token without lexeme"+ -- | Parse a single String literal, using a 'SubsumesToken' type. -- Returns the lexeme interpreted as a String literal. string_lit :: SubsumesToken t => SymbExpr t String@@ -546,68 +533,89 @@                                     return $ map (id *** f) as )  -- | --- Version of '<$$>' that ignores the semantic result of its second argument. +-- Variant of '<$$>' that ignores the semantic result of its second argument.  (<$$) :: (Show t, Ord t, IsSymbExpr s) => b -> s t a -> AltExpr t b f <$$ p = const f <$$> p infixl 4 <$$  -- | --- Version of '<**>' that ignores the semantic result of the first argument.+infixl 4 **>, <<**>, **>>>++-- | +-- Variant of '<**>' that ignores the semantic result of the first argument. (**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t b-l **>r = flip const .$. l <**> r-infixl 4 **>+l **> r = flip const .$. l <**> r +-- Variant of '<**>' that applies longest match on its left operand. +(**>>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t b+l **>>> r = flip const .$. l <**>>> r++-- Variant of '<**>' that ignores shortest match on its left operand.+(<<**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t b+l <<**>r = flip const .$. l <<<**> r+++infixl 4 <**, <<<**, <**>> -- | --- Version of '<**>' that ignores the semantic result of the second argument.+-- Variant of '<**>' that ignores the semantic result of the second argument. (<**) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t a l <** r = const .$. l <**> r -infixl 4 <** +-- | Variant of '<**' that applies longest match on its left operand.+(<**>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t a+l <**>> r = const .$. l <**>>> r ++-- | Variant '<**' that applies shortest match on its left operand+(<<<**) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t a+l <<<** r = const .$. l <<<**> r + -- | --- Version of '<::=' that prioritises productions from left-to-right (or top-to-bottom).+-- Variant of '<::=>' that prioritises productions from left-to-right (or top-to-bottom). x <::= altPs = mkNtRule True True x altPs  infixl 2 <::= --- | Try to apply a parser multiple times (0 or more). The results are returned in a list.--- In the case of ambiguity the largest list is returned.+-- | +-- Variant of '<:=>' that prioritises productions from left-to-right (or top-to-bottom).+x <:= altPs = mkNtRule False True x altPs +infixl 2 <:=++-- | Try to apply a parser multiple times (0 or more) with shortest match+-- applied to each occurrence of the parser. many :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]-many = multiple_ rassoc --- | Try to apply a parser multiple times (1 or more). The results are returned in a list.--- In the case of ambiguity the largest list is returned.+many = multiple_ (<<<**>)++-- | Try to apply a parser multiple times (1 or more) with shortest match+-- applied to each occurrence of the parser. many1 :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]-many1 = multiple1_ rassoc +many1 = multiple1_ (<<<**>)  --- | Try to apply a parser multiple times (0 or more). The results are returned in a list.--- In the case of ambiguity the largest list is returned.+-- | Try to apply a parser multiple times (0 or more) with longest match+-- applied to each occurrence of the parser. some :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]-some = multiple_ lassoc +some = multiple_ (<**>>>) --- | Try to apply a parser multiple times (1 or more). The results are returned in a list.--- In the case of ambiguity the largest list is returned.+-- | Try to apply a parser multiple times (1 or more) with longest match+-- applied to each occurrence of the parser. some1 :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]-some1 = multiple1_ lassoc+some1 = multiple1_ (<**>>>)   -- | Try to apply a parser multiple times (0 or more). The results are returned in a list. -- In the case of ambiguity the largest list is returned. multiple :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]-multiple = multiple_ id+multiple = multiple_ (<**>)  -- | Try to apply a parser multiple times (1 or more). The results are returned in a list. -- In the case of ambiguity the largest list is returned. multiple1 :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]-multiple1 = multiple1_ id+multiple1 = multiple1_ (<**>)  -- | Internal-multiple_ :: (Show t, Ord t, IsSymbExpr s) => (AltExpr t [a] -> AltExpr t [a]) ->-                s t a -> SymbExpr t [a] multiple_ disa p = let fresh = mkNt p "*" -                    in fresh <::=> disa ((:) <$$> p <**> multiple p) <||> satisfy []+                    in fresh <::=> ((:) <$$> p) `disa` (multiple_ disa p) <||> satisfy []  -- | Internal-multiple1_ :: (Show t, Ord t, IsSymbExpr s) => (AltExpr t [a] -> AltExpr t [a]) ->-                s t a -> SymbExpr t [a] multiple1_ disa p = let fresh = mkNt p "+"-                     in fresh <::=> disa ((:) <$$> p <**> multiple p)+                     in fresh <::=> ((:) <$$> p) `disa` (multiple_ disa p)  -- | Same as 'many' but with an additional separator. manySepBy :: (Show t, Ord t, IsSymbExpr s, IsSymbExpr s2, IsAltExpr s2) => @@ -642,55 +650,41 @@            (AltExpr t a -> SymbExpr t [a]) -> s1 t a -> s2 t b -> SymbExpr t [a] sepBy1 mult p c = mkRule $ (:) <$$> p <**> mult (c **> p) --- | Try to apply a parser once, but proceed if unsuccessful +-- | Like 'multipleSepBy1' but matching at least two occurrences of the +-- first argument. The returned list is therefore always of at least+-- length 2. At least one separator will be consumed.+multipleSepBy2 p s = mkRule $+  (:) <$$> p <** s <**> multipleSepBy1 p s++-- | Like 'multipleSepBy2' but matching the minimum number of +-- occurrences of the first argument as possible (at least 2).+someSepBy2 p s = mkRule $+  (:) <$$> p <** s <**> someSepBy1 p s++-- | Like 'multipleSepBy2' but matching the maximum number of+-- occurrences of the first argument as possible (at least 2).+manySepBy2 p s = mkRule $ +  (:) <$$> p <** s <**> manySepBy1 p s++-- | Make a piece of BNF optional, but proceed if unsuccessful  -- (yielding 'Nothing' as a result in that case). optional :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t (Maybe a) optional p = let fresh = mkNt p "?"                 in fresh <::=> Just <$$> p <||> satisfy Nothing  --- | --- Class for lifting to 'SymbExpr'.-class IsSymbExpr a where-    toSymb :: (Show t, Ord t) => a t b -> SymbExpr t b-    -- | Synonym of 'toSymb' for creating /derived combinators/. -    mkRule :: (Show t, Ord t) => a t b -> BNF t b-    mkRule = toSymb--instance IsSymbExpr AltExpr where-    toSymb = toSymb . OO . (:[]) --instance IsSymbExpr SymbExpr where-    toSymb = id --instance IsSymbExpr AltExprs where-    toSymb a = mkName <:=> a -        where mkName = "_toSb(" ++ intercalate ")|(" (map op (unOO a)) ++ ")_"-                where op (AltExpr (rhs,_,_)) = "(" ++ intercalate ")*(" (map show rhs) ++ ")"--- | --- Class for lifting to 'AltExprs'. -class HasAlts a where-    altsOf :: (Show t, Ord t) => a t b -> [AltExpr t b]--instance HasAlts AltExpr where-    altsOf = (:[])--instance HasAlts SymbExpr where-    altsOf = altsOf . toAlt--instance HasAlts AltExprs where-    altsOf = unOO ---- | --- Class for lifting to 'AltExpr'. -class IsAltExpr a where-    toAlt :: (Show t, Ord t) => a t b -> AltExpr t b--instance IsAltExpr AltExpr where-    toAlt = id--instance IsAltExpr SymbExpr where-    toAlt p = id <$$> p--instance IsAltExpr AltExprs where-    toAlt = toAlt . mkRule+-- | Place a piece of BNF /within/ two other BNF fragments, ignoring their semantics.+within :: BNF Token a -> BNF Token b -> BNF Token c -> BNF Token b+within l p r = mkRule $ l **> p <** r +-- | Place a piece of BNF between the characters '(' and ')'.+parens p = within (keychar '(') p (keychar ')')+-- | Place a piece of BNF between the characters '{' and '}'.+braces p = within (keychar '{') p (keychar '}')+-- | Place a piece of BNF between the characters '[' and ']'.+brackets p = within (keychar '[') p (keychar ']')+-- | Place a piece of BNF between the characters '<' and '>'.+angles p = within (keychar '<') p (keychar '>')+-- | Place a piece of BNF between two single quotes.+quotes p = within (keychar '\'') p (keychar '\'')+-- | Place a piece of BNF between two double quotes.+dquotes p = within (keychar '"') p (keychar '"')
src/GLL/Combinators/Lexer.hs view
@@ -57,6 +57,7 @@     <|> charsToInt  <$> optional (sym '-') <*> some (psym isDigit)     <|> upcast . IDLit . Just <$> identifiers lexsets      <|> upcast . AltIDLit . Just <$> altIdentifiers lexsets+    <|> upcast . CharLit . Just <$> lCharLit     <|> upcast . StringLit . Just <$> lStringLit     <|> lMore     where   @@ -76,3 +77,7 @@              where strChar =  sym '\\' *> sym '\"'                               <|> psym ((/=) '\"')                    toString inner = read ("\"" ++ inner ++ "\"")++            lCharLit = id <$ sym '\'' <*> charChar <* sym '\''+              where charChar = sym '\\' *> sym '\''+                                <|> psym ((/=) '\'')
src/GLL/Combinators/Options.hs view
@@ -20,7 +20,10 @@ type CombinatorOption     = PCOptions -> PCOptions  runOptions :: CombinatorOptions -> PCOptions-runOptions = foldr ($) defaultOptions+runOptions = runOptionsOn defaultOptions++runOptionsOn :: PCOptions -> CombinatorOptions -> PCOptions +runOptionsOn = foldr ($)  -- | The default options: no disambiguation. defaultOptions :: PCOptions
src/GLL/Combinators/Test/Interface.hs view
@@ -36,7 +36,7 @@ import GLL.Combinators.Interface import GLL.Parseable.Char () --- | Defines and executes some unit-tests +-- | Defines and executes multiple1 unit-tests  main = do     count <- newIORef 1     let test mref name p arg_pairs = do@@ -110,29 +110,29 @@     test Nothing "inline choice (1)" pX                 [("ab", "b"), ("ac", "c"), ("a", []), ("b", [])] -    let pX = "X" <::=> length <$$> many (char '1')-    test Nothing "many" pX [("", [0]), ("11", [2]), (replicate 12 '1', [12])]+    let pX = "X" <::=> length <$$> multiple (char '1')+    test Nothing "multiple" pX [("", [0]), ("11", [2]), (replicate 12 '1', [12])] -    let pX = "X" <::=> length <$$> some (char '1')-    test Nothing "some" pX [("", []), ("11", [2]), (replicate 12 '1', [12])]+    let pX = "X" <::=> length <$$> multiple1 (char '1')+    test Nothing "multiple1" pX [("", []), ("11", [2]), (replicate 12 '1', [12])] -    let pX = "X" <::=> 1 <$$ many (char 'a') <||> 2 <$$ many (char 'b')-    test Nothing "(many <||> many) <**> optional" (pX <** optional (char 'z'))+    let pX = "X" <::=> 1 <$$ multiple (char 'a') <||> 2 <$$ multiple (char 'b')+    test Nothing "(multiple <||> multiple) <**> optional" (pX <** optional (char 'z'))                 [("az", [1]), ("bz", [2]), ("z", [1,2])                 ,("", [1,2]), ("b", [2]), ("a", [1])]      let pX = "X" <::=> pY <** optional (char 'z')-         where pY = "Y" <::=> length <$$> many (char 'a')-                          <||> length <$$> some (char 'b') <** char 'e'-    test Nothing "many & some & optional" +         where pY = "Y" <::=> length <$$> multiple (char 'a')+                          <||> length <$$> multiple1 (char 'b') <** char 'e'+    test Nothing "multiple & multiple1 & optional"          pX  [("aaaz", [3]), ("bbbez", [3]), ("ez", []), ("z", [0])             ,("aa", [2]), ("bbe", [2])              ] -    -- many with nullable argument+    -- multiple with nullable argument     let pX = 1 <$$ char '1' <||> satisfy 0-    test Nothing "many (nullable arg)" -        (many pX) [("11", [[1,1]]), ("",[[]]), ("e", [])]+    test Nothing "multiple (nullable arg)" +        (multiple pX) [("11", [[1,1]]), ("",[[]]), ("e", [])]      --  Simple ambiguities     let pX = (++) <$$> pA <**> pB@@ -148,10 +148,10 @@             <||> 4 <$$ char 'd'     test Nothing "longambig" pX [("abcde", [[1,3],[2,4]]), ("abcdd", [])] -    let pX = "X" <::=> (1 <$$ some (char 'a') <||> 2 <$$ many (char 'b'))+    let pX = "X" <::=> (1 <$$ multiple1 (char 'a') <||> 2 <$$ multiple (char 'b'))         pY = "Y" <::=> (+) <$$> pX <**> pY                    <||> satisfy 0-    test Nothing "some & many & recursion + ambiguities" pY+    test Nothing "multiple1 & multiple & recursion + ambiguities" pY         [("ab", [3]),("aa", [1,2]), (replicate 10 'a', [1..10])]      let pX = "X" <::=>  1 <$$ char 'a' <||> satisfy 0@@ -201,10 +201,10 @@     putStrLn "Tests that use memoisation"      let tab = newMemoTable-        pX = "X" <::=> (1 <$$ some (char 'a') <||> 2 <$$ many (char 'b'))+        pX = "X" <::=> (1 <$$ multiple1 (char 'a') <||> 2 <$$ multiple (char 'b'))         pY = memo tab ("Y" <::=> (+) <$$> pX <**> pY                    <||> satisfy 0)-    test (Just tab) "some & many & recursion + ambiguities" pY+    test (Just tab) "multiple1 & multiple & recursion + ambiguities" pY         [("ab", [3]),("aa", [1,2]), (replicate 10 'a', [1..10])]      let tab = newMemoTable @@ -228,6 +228,76 @@         pY = memo tab ("Y" <::=> satisfy 0 <||> pX)     test (Just tab) "hidden left-recursion + infinite derivations" pX         [("", [0]), ("ab", [1]), ("ababab", [3])]++    putStrLn "Testing ambiguity reduction combinators"+    let pX = (++) <$$> pA <**>>> pB+        pA = "a" <$$ char 'a' <||> "aa" <$$ char 'a' <** char 'a'+        pB = "b" <$$ char 'a' <||> "bb" <$$ char 'a' <** char 'a' +    test Nothing "A<A" pX   [("aaa", ["aab"]),("aa", ["ab"])]++    let pX = (++) <$$> pA <<<**> pB+        pA = "a" <$$ char 'a' <||> "aa" <$$ char 'a' <** char 'a'+        pB = "b" <$$ char 'a' <||> "bb" <$$ char 'a' <** char 'a' +    test Nothing "A>A" pX   [("aaa", ["abb"]),("aa", ["ab"])] ++    let pX = "X" <:=> multiple pY+         where pY = 1 <$$ char '1' <||> 2 <$$ char '1' <** char '1'+    test Nothing "multiple" pX +      [("", [[]]), ("1", [[1]]), ("11", [[1,1],[2]]), ("111", [[1,1,1], [2,1], [1,2]])]++    let pX = "X" <:=> some pY+         where pY = 1 <$$ char '1' <||> 2 <$$ char '1' <** char '1'+    test Nothing "some" pX +      [("", [[]]), ("1", [[1]]), ("11", [[2]]), ("111", [[2,1]])]++{-+    -- a combinatar `fewest` (variant of multiple) should behave as follows+    let pX = "X" <:=> fewest pY+         where pY = 1 <$$ char '1' <||> 2 <$$ char '1' <** char '1'+    test Nothing "some" pX +      [("", [[]]), ("1", [[1]]), ("11", [[2]]), ("111", [[2,1], [1,2]])]+-}++    let pX = "X" <:=> many pY+         where pY = 1 <$$ char '1' <||> 2 <$$ char '1' <** char '1'+    test Nothing "many" pX +      [("", [[]]), ("1", [[1]]), ("11", [[1,1]]), ("111", [[1,1,1]])]+ +    let pX = "X" <:=> "1" <$$ char '1' <||> multipleSepBy (char '1') (char ';')+    test Nothing "multipleSepBy" pX+      [("", [""]), ("1", ["1", "1"]), ("1;1", ["11"])]++    -- pX matches epsilon, therefore leading to infinitely many derivations+    let pX :: BNF Char Int +        pX = "X" <::=> 1 <$$ char '1' <||> sum <$$> multipleSepBy pX (char ';')+    test Nothing "multipleSepBy2" pX+      [("", [0]), ("1", [1,1]), ("1;1", [2]), (";1", [1]),  (";1;1", [2])]++    let pX = "X" <:=> length <$$> multiple (char '1')+    test Nothing "multiple1" pX+      [("", [0]), ("11", [2]), (replicate 10 '1', [10])]++    let pX = "X" <:=> length <$$> multiple (char '1') <** char 'z'+    test Nothing "multiple2" pX+      [("", []), ("11z", [2]), (replicate 10 '1' ++ "z", [10])]++    let pX = "X" <:=> length <$$> multiple pEps <** char 'z'+          where pEps = satisfy () <||> () <$$ char '1'+    test Nothing "multiple & epsilon" pX+      [("", []), ("z", [0])]++    let pX :: BNF Char Int +        pX = "X" <::=> 1 <$$ char '1' <||> sum <$$> multipleSepBy pX (char ';')+    test Nothing "multipleSepBy and multiple" (multiple pX)+      -- why not ("", [[0]]) ??+      [("", [[]]), ("1", [[1],[1]]), ("1;1", [[1,0,1],[1,1],[2]])+      ,(";1;1", [[0,1,0,1],[0,1,1], [0,2], [1,0,1], [1,1], [2]])]+{-+    let pX :: BNF Char Int +        pX = "X" <::=> 1 <$$ char '1' <||> sum <$$> multipleSepBy pX (char ';')+    test Nothing "manySepBy and multiple" (many pX)+      -- why not ("", [[0]]) ??+      [("", [[]]), ("1", [[1],[1]]), ("1;1", [[1,0,1]])]-}   where     aho_S_5 = ["10101010100","10101011000","10101100100","10101101000","10101110000","10110010100","10110011000","10110100100","10110101000","10110110000","10111000100","10111001000","10111010000","10111100000","11001010100","11001011000","11001100100","11001101000","11001110000","11010010100","11010011000","11010100100","11010101000","11010110000","11011000100","11011001000","11011010000","11011100000","11100010100","11100011000","11100100100","11100101000","11100110000","11101000100","11101001000","11101010000","11101100000","11110000100","11110001000","11110010000","11110100000","11111000000"]
+ src/GLL/Combinators/Visit/Join.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE FlexibleInstances #-}++module GLL.Combinators.Visit.Join where++import GLL.Types.Grammar+import GLL.Types.Abstract+import GLL.Combinators.Visit.Sem+import GLL.Combinators.Visit.Grammar+import GLL.Combinators.Options++import Control.Compose (OO(..),unOO)+import Data.List (intercalate)+import Data.Text (pack)++-- | A combinator expression representing a symbol.+-- A 'SymbExpr' either represents a terminal or a nonterminal.+-- In the latter case it is constructed with (a variant of) '<:=>' and +-- adds a rule to the grammar of which the represented symbol is the +-- left-hand side.+data SymbExpr t a = SymbExpr (Symbol t, Grammar_Expr t, Sem_Symb t a)+-- | A combinator expression representing a BNF-grammar. The terminals of+-- the grammar are of type 't'. When used to parse, the expression yields+-- semantic results of type 'a'. +type BNF t a = SymbExpr t a+-- | +-- A combinator expression representing an alternative: +-- the right-hand side of a production.+data AltExpr t a = AltExpr ([Symbol t], Grammar_Expr t, Sem_Alt t a)++-- | A list of alternatives represents the right-hand side of a rule.+type AltExprs = OO [] AltExpr++mkNtRule :: (Show t, Ord t, HasAlts b) => Bool -> Bool -> String -> b t a -> SymbExpr t a+mkNtRule use_ctx left_biased x' altPs' =+    let vas1 = map (\(AltExpr (f,_,_)) -> f) altPs +        vas2 = map (\(AltExpr (_,s,_)) -> s) altPs+        vas3 = map (\(AltExpr (_,_,t)) -> t) altPs+        alts  = map (Prod x) vas1    +        altPs = altsOf altPs'+        x     = pack x'+    in SymbExpr (Nt x, grammar_nterm x alts vas2, sem_nterm use_ctx left_biased x alts vas3)++join_apply :: (Show t, Ord t, IsSymbExpr s) => (a -> b) -> s t a -> AltExpr t b+join_apply f p' = +    let SymbExpr (vpa1,vpa2,vpa3) = mkRule p' in AltExpr+          ([vpa1],grammar_apply vpa2, sem_apply f vpa3)++join_seq :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => +              CombinatorOptions -> i t (a -> b) -> s t a -> AltExpr t b+join_seq local_opts pl' pr' = +  let AltExpr (vimp1,vimp2,vimp3) = toAlt pl'+      SymbExpr (vpa1,vpa2,vpa3)  = mkRule pr' in AltExpr+  (vimp1++[vpa1], grammar_seq vimp2 vpa2, sem_seq local_opts vimp3 vpa3)++-- | +-- Class for lifting to 'SymbExpr'.+class IsSymbExpr a where+    toSymb :: (Show t, Ord t) => a t b -> SymbExpr t b+    -- | Synonym of 'toSymb' for creating /derived combinators/. +    mkRule :: (Show t, Ord t) => a t b -> BNF t b+    mkRule = toSymb++instance IsSymbExpr AltExpr where+    toSymb = toSymb . OO . (:[]) ++instance IsSymbExpr SymbExpr where+    toSymb = id ++instance IsSymbExpr AltExprs where+    toSymb a = mkNtRule False False mkName a +        where mkName = "_toSb(" ++ intercalate ")|(" (map op (unOO a)) ++ ")_"+                where op (AltExpr (rhs,_,_)) = "(" ++ intercalate ")*(" (map show rhs) ++ ")"+-- | +-- Class for lifting to 'AltExprs'. +class HasAlts a where+    altsOf :: (Show t, Ord t) => a t b -> [AltExpr t b]++instance HasAlts AltExpr where+    altsOf = (:[])++instance HasAlts SymbExpr where+    altsOf = altsOf . toAlt++instance HasAlts AltExprs where+    altsOf = unOO ++-- | +-- Class for lifting to 'AltExpr'. +class IsAltExpr a where+    toAlt :: (Show t, Ord t) => a t b -> AltExpr t b++instance IsAltExpr AltExpr where+    toAlt = id++instance IsAltExpr SymbExpr where+    toAlt p = join_apply id p++instance IsAltExpr AltExprs where+    toAlt = toAlt . mkRule+
src/GLL/Combinators/Visit/Sem.hs view
@@ -44,14 +44,14 @@         in do   as <- p opts ctx sppf arr l r                 return (maybe [] (const (map (op f) as)) $ sppf `pNodeLookup` ((alt,1),l,r)) -sem_seq :: Ord t => Sem_Alt t (a -> b) -> Sem_Symb t a -> Sem_Alt t b -sem_seq p q opts (alt@(Prod x rhs),j) ctx sppf arr l r = +sem_seq :: Ord t => CombinatorOptions -> Sem_Alt t (a -> b) -> Sem_Symb t a -> Sem_Alt t b +sem_seq local_opts p q opts (alt@(Prod x rhs),j) ctx sppf arr l r =      let ks      = maybe [] id $ sppf `pNodeLookup` ((alt,j), l, r)-        choices = case pivot_select opts of+        choices = case pivot_select (runOptionsOn opts local_opts) of                     Nothing      -> ks                     Just compare -> maximumsWith compare ks         seq k  = do     as      <- q opts ctx sppf arr k r-                        a2bs    <- p opts(alt,j-1) ctx sppf arr l k+                        a2bs    <- p opts (alt,j-1) ctx sppf arr l k                         return [ (k,a2b a) | (_,a2b) <- a2bs, a <- as ]     in do   ass <- forM choices seq             return (concat ass)
src/GLL/Parser.hs view
@@ -530,7 +530,7 @@                                 , error_message             :: String                                 } -resultFromMutable :: (Show t, Ord t) => Input t -> Flags -> Mutable t -> SNode t -> ParseResult t+resultFromMutable :: Parseable t => Input t -> Flags -> Mutable t -> SNode t -> ParseResult t resultFromMutable inp flags mutable s_node@(s, l, m) =     let u           = mut_descriptors mutable         gss         = mut_gss mutable@@ -551,19 +551,20 @@         sppf@(sMap, iMap, pMap, eMap) = mut_sppf mutable     in ParseResult sppf (mut_success mutable) usize s_nodes m i_nodes p_nodes sppf_edges gss_nodes gss_edges (renderErrors inp flags (mut_mismatches mutable)) -renderErrors :: Show t => Input t -> Flags -> MisMatches t -> String+renderErrors :: Parseable t => Input t -> Flags -> MisMatches t -> String renderErrors inp flags mm = render doc   where  n       = max_errors flags         locs    = reverse (IM.assocs mm)         doc     = text ("Unsuccessful parse, showing "++ show n ++ " furthest matches") $+$                     foldr (\loc -> (ppLoc loc $+$)) PP.empty locs -        ppLoc (k, ts) = text ("did not match at position " ++ show k ++ ":") $+$-                            nest 4 (text (show token)) $+$+        ppLoc (k, ts) = text ("did not match at position " ++ show k ++ ", where we find " ++ lexeme) $+$+                            nest 4 (text "Found" <+> ppExp token) $+$                             nest 4 (text "expected:") $+$                                 nest 8 (vcat (map ppExp (S.toList ts)))          where  token = inp A.! k-        ppExp = text . show+                lexeme = concatMap unlex (take 5 (drop k (A.elems inp)))+        ppExp t = text (unlex t) <+> text "AKA" <+> text (show t)  instance Show (ParseResult t) where     show res | res_success res = result_string
src/GLL/Types/Abstract.hs view
@@ -57,6 +57,7 @@            | IntLit     (Maybe Int)            | BoolLit    (Maybe Bool)            | StringLit  (Maybe String)+           | CharLit    (Maybe Char)            | IDLit      (Maybe String)            -- | alternative identifiers, for example functions vs. constructors (as in Haskell).            | AltIDLit   (Maybe String) @@ -83,6 +84,11 @@     -- while the grammar tokens do not     matches :: a -> a -> Bool +    -- | This function pretty-prints the Parseable type by displaying its lexeme.+    -- Default implementation is 'show', which should be replaced for prettier error messages.+    unlex :: a -> String+    unlex = show+ -- | Class whose members are super-types of 'Token'. class SubsumesToken a where     upcast :: Token -> a@@ -106,6 +112,8 @@     show (BoolLit _)          = "<bool>"     show (StringLit (Just s)) = "string(\"" ++ s ++ "\")"     show (StringLit _)        = "<string>"+    show (CharLit (Just c))   = "char-literal('" ++ [c] ++ "')"+    show (CharLit Nothing)    = "<char>"     show (AltIDLit (Just id)) = "altid(\"" ++ id ++ "\")"     show (AltIDLit Nothing)   = "<altid>"     show (IDLit  (Just id))   = "id(\"" ++ id ++ "\")"@@ -117,12 +125,15 @@     eos = EOS     eps = Epsilon +    unlex = unlexToken+     Token k _   `matches` Token k' _   = k' == k     Char c      `matches` Char c'      = c' == c     Keyword k   `matches` Keyword k'   = k' == k     EOS         `matches` EOS          = True     Epsilon     `matches` Epsilon      = True     StringLit _ `matches` StringLit _  = True+    CharLit _   `matches` CharLit _    = True     IntLit _    `matches` IntLit _     = True     BoolLit _   `matches` BoolLit _    = True     AltIDLit _  `matches` AltIDLit _   = True@@ -130,3 +141,19 @@     _           `matches` _            = False  +-- | Pretty-prints a list of 'Token's as a concatenation of their lexemes.+unlexTokens :: [Token] -> String+unlexTokens = Prelude.concatMap unlexToken ++unlexToken :: Token -> String+unlexToken t = case t of +          Char c              -> [c]+          Keyword s           -> s+          IntLit (Just i)     -> show i+          BoolLit (Just b)    -> show b+          StringLit (Just s)  -> s+          CharLit (Just c)    -> [c]+          AltIDLit (Just s)   -> s+          IDLit (Just s)      -> s+          Token _ (Just s)    -> s+          _                   -> ""