-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A parser for SQL queries -- -- A parser for SQL queries. Parses most SQL:2011 queries. Please see the -- homepage for more information -- http://jakewheat.github.io/simple-sql-parser/. @package simple-sql-parser @version 0.4.2 -- | The AST for SQL queries. module Language.SQL.SimpleSQL.Syntax -- | Represents a value expression. This is used for the expressions in -- select lists. It is also used for expressions in where, group by, -- having, order by and so on. data ValueExpr -- | a numeric literal optional decimal point, e+- integral exponent, e.g -- -- NumLit :: String -> ValueExpr -- | string literal, currently only basic strings between single quotes -- with a single quote escaped using '' StringLit :: String -> ValueExpr -- | text of interval literal, units of interval precision, e.g. interval 3 -- days (3) IntervalLit :: Maybe Bool -> String -> IntervalTypeField -> Maybe IntervalTypeField -> ValueExpr -- | true if + used, false if - used [ilSign] :: ValueExpr -> Maybe Bool -- | literal text [ilLiteral] :: ValueExpr -> String [ilFrom] :: ValueExpr -> IntervalTypeField [ilTo] :: ValueExpr -> Maybe IntervalTypeField -- | identifier with parts separated by dots Iden :: [Name] -> ValueExpr -- | star, as in select *, t.*, count(*) Star :: ValueExpr -- | function application (anything that looks like c style function -- application syntactically) App :: [Name] -> [ValueExpr] -> ValueExpr -- | aggregate application, which adds distinct or all, and order by, to -- regular function application AggregateApp :: [Name] -> SetQuantifier -> [ValueExpr] -> [SortSpec] -> Maybe ValueExpr -> ValueExpr -- | aggregate function name [aggName] :: ValueExpr -> [Name] -- | distinct [aggDistinct] :: ValueExpr -> SetQuantifier -- | args [aggArgs] :: ValueExpr -> [ValueExpr] -- | order by [aggOrderBy] :: ValueExpr -> [SortSpec] -- | filter [aggFilter] :: ValueExpr -> Maybe ValueExpr -- | aggregates with within group AggregateAppGroup :: [Name] -> [ValueExpr] -> [SortSpec] -> ValueExpr -- | aggregate function name [aggName] :: ValueExpr -> [Name] -- | args [aggArgs] :: ValueExpr -> [ValueExpr] -- | within group [aggGroup] :: ValueExpr -> [SortSpec] -- | window application, which adds over (partition by a order by b) to -- regular function application. Explicit frames are not currently -- supported WindowApp :: [Name] -> [ValueExpr] -> [ValueExpr] -> [SortSpec] -> Maybe Frame -> ValueExpr -- | window function name [wnName] :: ValueExpr -> [Name] -- | args [wnArgs] :: ValueExpr -> [ValueExpr] -- | partition by [wnPartition] :: ValueExpr -> [ValueExpr] -- | order by [wnOrderBy] :: ValueExpr -> [SortSpec] -- | frame clause [wnFrame] :: ValueExpr -> Maybe Frame -- | Infix binary operators. This is used for symbol operators (a + b), -- keyword operators (a and b) and multiple keyword operators (a is -- similar to b) BinOp :: ValueExpr -> [Name] -> ValueExpr -> ValueExpr -- | Prefix unary operators. This is used for symbol operators, keyword -- operators and multiple keyword operators. PrefixOp :: [Name] -> ValueExpr -> ValueExpr -- | Postfix unary operators. This is used for symbol operators, keyword -- operators and multiple keyword operators. PostfixOp :: [Name] -> ValueExpr -> ValueExpr -- | Used for ternary, mixfix and other non orthodox operators. Currently -- used for row constructors, and for between. SpecialOp :: [Name] -> [ValueExpr] -> ValueExpr -- | Used for the operators which look like functions except the arguments -- are separated by keywords instead of commas. The maybe is for the -- first unnamed argument if it is present, and the list is for the -- keyword argument pairs. SpecialOpK :: [Name] -> (Maybe ValueExpr) -> [(String, ValueExpr)] -> ValueExpr -- | case expression. both flavours supported Case :: Maybe ValueExpr -> [([ValueExpr], ValueExpr)] -> Maybe ValueExpr -> ValueExpr -- | test value [caseTest] :: ValueExpr -> Maybe ValueExpr -- | when branches [caseWhens] :: ValueExpr -> [([ValueExpr], ValueExpr)] -- | else value [caseElse] :: ValueExpr -> Maybe ValueExpr Parens :: ValueExpr -> ValueExpr -- | cast(a as typename) Cast :: ValueExpr -> TypeName -> ValueExpr -- | prefix 'typed literal', e.g. int '42' TypedLit :: TypeName -> String -> ValueExpr -- | exists, all, any, some subqueries SubQueryExpr :: SubQueryExprType -> QueryExpr -> ValueExpr -- | in list literal and in subquery, if the bool is false it means not in -- was used ('a not in (1,2)') In :: Bool -> ValueExpr -> InPredValue -> ValueExpr -- | Represents a ? in a parameterized query Parameter :: ValueExpr -- | represents a host parameter, e.g. :a. The Maybe String is for the -- indicator, e.g. :var indicator :nl HostParameter :: String -> (Maybe String) -> ValueExpr QuantifiedComparison :: ValueExpr -> [Name] -> CompPredQuantifier -> QueryExpr -> ValueExpr Match :: ValueExpr -> Bool -> QueryExpr -> ValueExpr -- | represents an array access expression, or an array ctor e.g. a[3]. The -- first valueExpr is the array, the second is the subscripts/ctor args Array :: ValueExpr -> [ValueExpr] -> ValueExpr -- | this is used for the query expression version of array constructors, -- e.g. array(select * from t) ArrayCtor :: QueryExpr -> ValueExpr CSStringLit :: String -> String -> ValueExpr Escape :: ValueExpr -> Char -> ValueExpr UEscape :: ValueExpr -> Char -> ValueExpr Collate :: ValueExpr -> [Name] -> ValueExpr MultisetBinOp :: ValueExpr -> CombineOp -> SetQuantifier -> ValueExpr -> ValueExpr MultisetCtor :: [ValueExpr] -> ValueExpr MultisetQueryCtor :: QueryExpr -> ValueExpr NextValueFor :: [Name] -> ValueExpr VEComment :: [Comment] -> ValueExpr -> ValueExpr -- | Represents an identifier name, which can be quoted or unquoted. data Name Name :: String -> Name QName :: String -> Name UQName :: String -> Name -- | dialect quoted name, the fields are start quote, end quote and the -- string itself, e.g. something is parsed to DQName "`" "`" -- "something, and $a$ test $a$ is parsed to DQName "$a$" "$a" " test " DQName :: String -> String -> String -> Name -- | Represents a type name, used in casts. data TypeName TypeName :: [Name] -> TypeName PrecTypeName :: [Name] -> Integer -> TypeName PrecScaleTypeName :: [Name] -> Integer -> Integer -> TypeName PrecLengthTypeName :: [Name] -> Integer -> (Maybe PrecMultiplier) -> (Maybe PrecUnits) -> TypeName CharTypeName :: [Name] -> (Maybe Integer) -> [Name] -> [Name] -> TypeName TimeTypeName :: [Name] -> (Maybe Integer) -> Bool -> TypeName RowTypeName :: [(Name, TypeName)] -> TypeName IntervalTypeName :: IntervalTypeField -> (Maybe IntervalTypeField) -> TypeName ArrayTypeName :: TypeName -> (Maybe Integer) -> TypeName MultisetTypeName :: TypeName -> TypeName data IntervalTypeField Itf :: String -> (Maybe (Integer, Maybe Integer)) -> IntervalTypeField data PrecMultiplier PrecK :: PrecMultiplier PrecM :: PrecMultiplier PrecG :: PrecMultiplier PrecT :: PrecMultiplier PrecP :: PrecMultiplier data PrecUnits PrecCharacters :: PrecUnits PrecOctets :: PrecUnits -- | Represents the Distinct or All keywords, which can be used before a -- select list, in an aggregate/window function application, or in a -- query expression set operator. data SetQuantifier SQDefault :: SetQuantifier Distinct :: SetQuantifier All :: SetQuantifier -- | Represents one field in an order by list. data SortSpec SortSpec :: ValueExpr -> Direction -> NullsOrder -> SortSpec -- | The direction for a column in order by. data Direction DirDefault :: Direction Asc :: Direction Desc :: Direction -- | Represents 'nulls first' or 'nulls last' in an order by clause. data NullsOrder NullsOrderDefault :: NullsOrder NullsFirst :: NullsOrder NullsLast :: NullsOrder -- | Used for 'expr in (value expression list)', and 'expr in (subquery)' -- syntax. data InPredValue InList :: [ValueExpr] -> InPredValue InQueryExpr :: QueryExpr -> InPredValue -- | A subquery in a value expression. data SubQueryExprType -- | exists (query expr) SqExists :: SubQueryExprType -- | unique (query expr) SqUnique :: SubQueryExprType -- | a scalar subquery SqSq :: SubQueryExprType data CompPredQuantifier CPAny :: CompPredQuantifier CPSome :: CompPredQuantifier CPAll :: CompPredQuantifier -- | Represents the frame clause of a window this can be [range | rows] -- frame_start or [range | rows] between frame_start and frame_end data Frame FrameFrom :: FrameRows -> FramePos -> Frame FrameBetween :: FrameRows -> FramePos -> FramePos -> Frame -- | Represents whether a window frame clause is over rows or ranges. data FrameRows FrameRows :: FrameRows FrameRange :: FrameRows -- | represents the start or end of a frame data FramePos UnboundedPreceding :: FramePos Preceding :: ValueExpr -> FramePos Current :: FramePos Following :: ValueExpr -> FramePos UnboundedFollowing :: FramePos -- | Represents a query expression, which can be: -- -- data QueryExpr Select :: SetQuantifier -> [(ValueExpr, Maybe Name)] -> [TableRef] -> Maybe ValueExpr -> [GroupingExpr] -> Maybe ValueExpr -> [SortSpec] -> Maybe ValueExpr -> Maybe ValueExpr -> QueryExpr [qeSetQuantifier] :: QueryExpr -> SetQuantifier -- | the expressions and the column aliases [qeSelectList] :: QueryExpr -> [(ValueExpr, Maybe Name)] [qeFrom] :: QueryExpr -> [TableRef] [qeWhere] :: QueryExpr -> Maybe ValueExpr [qeGroupBy] :: QueryExpr -> [GroupingExpr] [qeHaving] :: QueryExpr -> Maybe ValueExpr [qeOrderBy] :: QueryExpr -> [SortSpec] [qeOffset] :: QueryExpr -> Maybe ValueExpr [qeFetchFirst] :: QueryExpr -> Maybe ValueExpr CombineQueryExpr :: QueryExpr -> CombineOp -> SetQuantifier -> Corresponding -> QueryExpr -> QueryExpr [qe0] :: QueryExpr -> QueryExpr [qeCombOp] :: QueryExpr -> CombineOp [qeSetQuantifier] :: QueryExpr -> SetQuantifier [qeCorresponding] :: QueryExpr -> Corresponding [qe1] :: QueryExpr -> QueryExpr With :: Bool -> [(Alias, QueryExpr)] -> QueryExpr -> QueryExpr [qeWithRecursive] :: QueryExpr -> Bool [qeViews] :: QueryExpr -> [(Alias, QueryExpr)] [qeQueryExpression] :: QueryExpr -> QueryExpr Values :: [[ValueExpr]] -> QueryExpr Table :: [Name] -> QueryExpr QEComment :: [Comment] -> QueryExpr -> QueryExpr -- | Helper/'default' value for query exprs to make creating query expr -- values a little easier. It is defined like this: -- --
--   makeSelect :: QueryExpr
--   makeSelect = Select {qeSetQuantifier = SQDefault
--                       ,qeSelectList = []
--                       ,qeFrom = []
--                       ,qeWhere = Nothing
--                       ,qeGroupBy = []
--                       ,qeHaving = Nothing
--                       ,qeOrderBy = []
--                       ,qeOffset = Nothing
--                       ,qeFetchFirst = Nothing}
--   
makeSelect :: QueryExpr -- | Query expression set operators. data CombineOp Union :: CombineOp Except :: CombineOp Intersect :: CombineOp -- | Corresponding, an option for the set operators. data Corresponding Corresponding :: Corresponding Respectively :: Corresponding -- | Represents an alias for a table valued expression, used in with -- queries and in from alias, e.g. select a from t u, select a from t -- u(b), with a(c) as select 1, select * from a. data Alias Alias :: Name -> (Maybe [Name]) -> Alias -- | Represents an item in a group by clause. data GroupingExpr GroupingParens :: [GroupingExpr] -> GroupingExpr Cube :: [GroupingExpr] -> GroupingExpr Rollup :: [GroupingExpr] -> GroupingExpr GroupingSets :: [GroupingExpr] -> GroupingExpr SimpleGroup :: ValueExpr -> GroupingExpr -- | Represents a entry in the csv of tables in the from clause. data TableRef -- | from t / from s.t TRSimple :: [Name] -> TableRef -- | from a join b, the bool is true if natural was used TRJoin :: TableRef -> Bool -> JoinType -> TableRef -> (Maybe JoinCondition) -> TableRef -- | from (a) TRParens :: TableRef -> TableRef -- | from a as b(c,d) TRAlias :: TableRef -> Alias -> TableRef -- | from (query expr) TRQueryExpr :: QueryExpr -> TableRef -- | from function(args) TRFunction :: [Name] -> [ValueExpr] -> TableRef -- | from lateral t TRLateral :: TableRef -> TableRef -- | The type of a join. data JoinType JInner :: JoinType JLeft :: JoinType JRight :: JoinType JFull :: JoinType JCross :: JoinType -- | The join condition. data JoinCondition -- | on expr JoinOn :: ValueExpr -> JoinCondition -- | using (column list) JoinUsing :: [Name] -> JoinCondition -- | Used to set the dialect used for parsing and pretty printing, very -- unfinished at the moment. data Dialect SQL2011 :: Dialect MySQL :: Dialect -- | Comment. Useful when generating SQL code programmatically. data Comment BlockComment :: String -> Comment instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.InPredValue instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.InPredValue instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.InPredValue instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.InPredValue instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.FramePos instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.FramePos instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.FramePos instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.FramePos instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.Frame instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.Frame instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.Frame instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.Frame instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.SortSpec instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.SortSpec instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.SortSpec instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.SortSpec instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.GroupingExpr instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.GroupingExpr instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.GroupingExpr instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.GroupingExpr instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.JoinCondition instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.JoinCondition instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.JoinCondition instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.JoinCondition instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.TableRef instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.TableRef instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.TableRef instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.TableRef instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.QueryExpr instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.QueryExpr instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.QueryExpr instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.QueryExpr instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.ValueExpr instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.ValueExpr instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.ValueExpr instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.ValueExpr instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.Comment instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.Comment instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.Comment instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.Comment instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.Dialect instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.Dialect instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.Dialect instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.Dialect instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.JoinType instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.JoinType instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.JoinType instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.JoinType instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.Alias instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.Alias instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.Alias instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.Alias instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.Corresponding instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.Corresponding instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.Corresponding instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.Corresponding instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.CombineOp instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.CombineOp instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.CombineOp instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.CombineOp instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.Direction instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.Direction instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.Direction instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.Direction instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.SetQuantifier instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.SetQuantifier instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.SetQuantifier instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.SetQuantifier instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.FrameRows instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.FrameRows instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.FrameRows instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.FrameRows instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.NullsOrder instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.NullsOrder instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.NullsOrder instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.NullsOrder instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.CompPredQuantifier instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.CompPredQuantifier instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.CompPredQuantifier instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.CompPredQuantifier instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.SubQueryExprType instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.SubQueryExprType instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.SubQueryExprType instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.SubQueryExprType instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.TypeName instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.TypeName instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.TypeName instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.TypeName instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.PrecUnits instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.PrecUnits instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.PrecUnits instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.PrecUnits instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.PrecMultiplier instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.PrecMultiplier instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.PrecMultiplier instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.PrecMultiplier instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.IntervalTypeField instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.IntervalTypeField instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.IntervalTypeField instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.IntervalTypeField instance Data.Data.Data Language.SQL.SimpleSQL.Syntax.Name instance GHC.Read.Read Language.SQL.SimpleSQL.Syntax.Name instance GHC.Show.Show Language.SQL.SimpleSQL.Syntax.Name instance GHC.Classes.Eq Language.SQL.SimpleSQL.Syntax.Name -- | These is the pretty printing functions, which produce SQL source from -- ASTs. The code attempts to format the output in a readable way. module Language.SQL.SimpleSQL.Pretty -- | Convert a query expr ast to concrete syntax. prettyQueryExpr :: Dialect -> QueryExpr -> String -- | Convert a value expr ast to concrete syntax. prettyValueExpr :: Dialect -> ValueExpr -> String -- | Convert a list of query exprs to concrete syntax. A semi colon is -- inserted after each query expr. prettyQueryExprs :: Dialect -> [QueryExpr] -> String -- | This is the module with the parser functions. module Language.SQL.SimpleSQL.Parser -- | Parses a query expr, trailing semicolon optional. parseQueryExpr :: Dialect -> FilePath -> Maybe (Int, Int) -> String -> Either ParseError QueryExpr -- | Parses a value expression. parseValueExpr :: Dialect -> FilePath -> Maybe (Int, Int) -> String -> Either ParseError ValueExpr -- | Parses a list of query expressions, with semi colons between them. The -- final semicolon is optional. parseQueryExprs :: Dialect -> FilePath -> Maybe (Int, Int) -> String -> Either ParseError [QueryExpr] -- | Type to represent parse errors. data ParseError ParseError :: String -> FilePath -> (Int, Int) -> String -> ParseError -- | contains the error message [peErrorString] :: ParseError -> String -- | filename location for the error [peFilename] :: ParseError -> FilePath -- | line number and column number location for the error [pePosition] :: ParseError -> (Int, Int) -- | formatted error with the position, error message and source context [peFormattedError] :: ParseError -> String