Cabal-syntax-3.12.1.0: A library for working with .cabal files
LicenseBSD3
Maintainercabal-devel@haskell.org
Portabilityportable
Safe HaskellSafe-Inferred
LanguageHaskell2010

Distribution.Fields.Parser

Description

 
Synopsis

Types

data Field ann Source #

A Cabal-like file consists of a series of fields (foo: bar) and sections (library ...).

Constructors

Field !(Name ann) [FieldLine ann] 
Section !(Name ann) [SectionArg ann] [Field ann] 

Instances

Instances details
Foldable Field Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

fold :: Monoid m => Field m -> m #

foldMap :: Monoid m => (a -> m) -> Field a -> m #

foldMap' :: Monoid m => (a -> m) -> Field a -> m #

foldr :: (a -> b -> b) -> b -> Field a -> b #

foldr' :: (a -> b -> b) -> b -> Field a -> b #

foldl :: (b -> a -> b) -> b -> Field a -> b #

foldl' :: (b -> a -> b) -> b -> Field a -> b #

foldr1 :: (a -> a -> a) -> Field a -> a #

foldl1 :: (a -> a -> a) -> Field a -> a #

toList :: Field a -> [a] #

null :: Field a -> Bool #

length :: Field a -> Int #

elem :: Eq a => a -> Field a -> Bool #

maximum :: Ord a => Field a -> a #

minimum :: Ord a => Field a -> a #

sum :: Num a => Field a -> a #

product :: Num a => Field a -> a #

Foldable1 Field Source #

Since: 3.12.0.0

Instance details

Defined in Distribution.Fields.Field

Methods

fold1 :: Semigroup m => Field m -> m #

foldMap1 :: Semigroup m => (a -> m) -> Field a -> m #

foldMap1' :: Semigroup m => (a -> m) -> Field a -> m #

toNonEmpty :: Field a -> NonEmpty a #

maximum :: Ord a => Field a -> a #

minimum :: Ord a => Field a -> a #

head :: Field a -> a #

last :: Field a -> a #

foldrMap1 :: (a -> b) -> (a -> b -> b) -> Field a -> b #

foldlMap1' :: (a -> b) -> (b -> a -> b) -> Field a -> b #

foldlMap1 :: (a -> b) -> (b -> a -> b) -> Field a -> b #

foldrMap1' :: (a -> b) -> (a -> b -> b) -> Field a -> b #

Traversable Field Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

traverse :: Applicative f => (a -> f b) -> Field a -> f (Field b) #

sequenceA :: Applicative f => Field (f a) -> f (Field a) #

mapM :: Monad m => (a -> m b) -> Field a -> m (Field b) #

sequence :: Monad m => Field (m a) -> m (Field a) #

Functor Field Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

fmap :: (a -> b) -> Field a -> Field b #

(<$) :: a -> Field b -> Field a #

Show ann => Show (Field ann) Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

showsPrec :: Int -> Field ann -> ShowS #

show :: Field ann -> String #

showList :: [Field ann] -> ShowS #

Eq ann => Eq (Field ann) Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

(==) :: Field ann -> Field ann -> Bool #

(/=) :: Field ann -> Field ann -> Bool #

Ord ann => Ord (Field ann) Source #

Since: 3.12.0.0

Instance details

Defined in Distribution.Fields.Field

Methods

compare :: Field ann -> Field ann -> Ordering #

(<) :: Field ann -> Field ann -> Bool #

(<=) :: Field ann -> Field ann -> Bool #

(>) :: Field ann -> Field ann -> Bool #

(>=) :: Field ann -> Field ann -> Bool #

max :: Field ann -> Field ann -> Field ann #

min :: Field ann -> Field ann -> Field ann #

data Name ann Source #

A field name.

Invariant: ByteString is lower-case ASCII.

Constructors

Name !ann !FieldName 

Instances

Instances details
Foldable Name Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

fold :: Monoid m => Name m -> m #

foldMap :: Monoid m => (a -> m) -> Name a -> m #

foldMap' :: Monoid m => (a -> m) -> Name a -> m #

foldr :: (a -> b -> b) -> b -> Name a -> b #

foldr' :: (a -> b -> b) -> b -> Name a -> b #

foldl :: (b -> a -> b) -> b -> Name a -> b #

foldl' :: (b -> a -> b) -> b -> Name a -> b #

foldr1 :: (a -> a -> a) -> Name a -> a #

foldl1 :: (a -> a -> a) -> Name a -> a #

toList :: Name a -> [a] #

null :: Name a -> Bool #

length :: Name a -> Int #

elem :: Eq a => a -> Name a -> Bool #

maximum :: Ord a => Name a -> a #

minimum :: Ord a => Name a -> a #

sum :: Num a => Name a -> a #

product :: Num a => Name a -> a #

Foldable1 Name Source #

Since: 3.12.0.0

Instance details

Defined in Distribution.Fields.Field

Methods

fold1 :: Semigroup m => Name m -> m #

foldMap1 :: Semigroup m => (a -> m) -> Name a -> m #

foldMap1' :: Semigroup m => (a -> m) -> Name a -> m #

toNonEmpty :: Name a -> NonEmpty a #

maximum :: Ord a => Name a -> a #

minimum :: Ord a => Name a -> a #

head :: Name a -> a #

last :: Name a -> a #

foldrMap1 :: (a -> b) -> (a -> b -> b) -> Name a -> b #

foldlMap1' :: (a -> b) -> (b -> a -> b) -> Name a -> b #

foldlMap1 :: (a -> b) -> (b -> a -> b) -> Name a -> b #

foldrMap1' :: (a -> b) -> (a -> b -> b) -> Name a -> b #

Traversable Name Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

traverse :: Applicative f => (a -> f b) -> Name a -> f (Name b) #

sequenceA :: Applicative f => Name (f a) -> f (Name a) #

mapM :: Monad m => (a -> m b) -> Name a -> m (Name b) #

sequence :: Monad m => Name (m a) -> m (Name a) #

Functor Name Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

fmap :: (a -> b) -> Name a -> Name b #

(<$) :: a -> Name b -> Name a #

Show ann => Show (Name ann) Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

showsPrec :: Int -> Name ann -> ShowS #

show :: Name ann -> String #

showList :: [Name ann] -> ShowS #

Eq ann => Eq (Name ann) Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

(==) :: Name ann -> Name ann -> Bool #

(/=) :: Name ann -> Name ann -> Bool #

Ord ann => Ord (Name ann) Source #

Since: 3.12.0.0

Instance details

Defined in Distribution.Fields.Field

Methods

compare :: Name ann -> Name ann -> Ordering #

(<) :: Name ann -> Name ann -> Bool #

(<=) :: Name ann -> Name ann -> Bool #

(>) :: Name ann -> Name ann -> Bool #

(>=) :: Name ann -> Name ann -> Bool #

max :: Name ann -> Name ann -> Name ann #

min :: Name ann -> Name ann -> Name ann #

data FieldLine ann Source #

A line of text representing the value of a field from a Cabal file. A field may contain multiple lines.

Invariant: ByteString has no newlines.

Constructors

FieldLine !ann !ByteString 

Instances

Instances details
Foldable FieldLine Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

fold :: Monoid m => FieldLine m -> m #

foldMap :: Monoid m => (a -> m) -> FieldLine a -> m #

foldMap' :: Monoid m => (a -> m) -> FieldLine a -> m #

foldr :: (a -> b -> b) -> b -> FieldLine a -> b #

foldr' :: (a -> b -> b) -> b -> FieldLine a -> b #

foldl :: (b -> a -> b) -> b -> FieldLine a -> b #

foldl' :: (b -> a -> b) -> b -> FieldLine a -> b #

foldr1 :: (a -> a -> a) -> FieldLine a -> a #

foldl1 :: (a -> a -> a) -> FieldLine a -> a #

toList :: FieldLine a -> [a] #

null :: FieldLine a -> Bool #

length :: FieldLine a -> Int #

elem :: Eq a => a -> FieldLine a -> Bool #

maximum :: Ord a => FieldLine a -> a #

minimum :: Ord a => FieldLine a -> a #

sum :: Num a => FieldLine a -> a #

product :: Num a => FieldLine a -> a #

Foldable1 FieldLine Source #

Since: 3.12.0.0

Instance details

Defined in Distribution.Fields.Field

Methods

fold1 :: Semigroup m => FieldLine m -> m #

foldMap1 :: Semigroup m => (a -> m) -> FieldLine a -> m #

foldMap1' :: Semigroup m => (a -> m) -> FieldLine a -> m #

toNonEmpty :: FieldLine a -> NonEmpty a #

maximum :: Ord a => FieldLine a -> a #

minimum :: Ord a => FieldLine a -> a #

head :: FieldLine a -> a #

last :: FieldLine a -> a #

foldrMap1 :: (a -> b) -> (a -> b -> b) -> FieldLine a -> b #

foldlMap1' :: (a -> b) -> (b -> a -> b) -> FieldLine a -> b #

foldlMap1 :: (a -> b) -> (b -> a -> b) -> FieldLine a -> b #

foldrMap1' :: (a -> b) -> (a -> b -> b) -> FieldLine a -> b #

Traversable FieldLine Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

traverse :: Applicative f => (a -> f b) -> FieldLine a -> f (FieldLine b) #

sequenceA :: Applicative f => FieldLine (f a) -> f (FieldLine a) #

mapM :: Monad m => (a -> m b) -> FieldLine a -> m (FieldLine b) #

sequence :: Monad m => FieldLine (m a) -> m (FieldLine a) #

Functor FieldLine Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

fmap :: (a -> b) -> FieldLine a -> FieldLine b #

(<$) :: a -> FieldLine b -> FieldLine a #

Show ann => Show (FieldLine ann) Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

showsPrec :: Int -> FieldLine ann -> ShowS #

show :: FieldLine ann -> String #

showList :: [FieldLine ann] -> ShowS #

Eq ann => Eq (FieldLine ann) Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

(==) :: FieldLine ann -> FieldLine ann -> Bool #

(/=) :: FieldLine ann -> FieldLine ann -> Bool #

Ord ann => Ord (FieldLine ann) Source #

Since: 3.12.0.0

Instance details

Defined in Distribution.Fields.Field

Methods

compare :: FieldLine ann -> FieldLine ann -> Ordering #

(<) :: FieldLine ann -> FieldLine ann -> Bool #

(<=) :: FieldLine ann -> FieldLine ann -> Bool #

(>) :: FieldLine ann -> FieldLine ann -> Bool #

(>=) :: FieldLine ann -> FieldLine ann -> Bool #

max :: FieldLine ann -> FieldLine ann -> FieldLine ann #

min :: FieldLine ann -> FieldLine ann -> FieldLine ann #

data SectionArg ann Source #

Section arguments, e.g. name of the library

Constructors

SecArgName !ann !ByteString

identifier, or something which looks like number. Also many dot numbers, i.e. "7.6.3"

SecArgStr !ann !ByteString

quoted string

SecArgOther !ann !ByteString

everything else, mm. operators (e.g. in if-section conditionals)

Instances

Instances details
Foldable SectionArg Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

fold :: Monoid m => SectionArg m -> m #

foldMap :: Monoid m => (a -> m) -> SectionArg a -> m #

foldMap' :: Monoid m => (a -> m) -> SectionArg a -> m #

foldr :: (a -> b -> b) -> b -> SectionArg a -> b #

foldr' :: (a -> b -> b) -> b -> SectionArg a -> b #

foldl :: (b -> a -> b) -> b -> SectionArg a -> b #

foldl' :: (b -> a -> b) -> b -> SectionArg a -> b #

foldr1 :: (a -> a -> a) -> SectionArg a -> a #

foldl1 :: (a -> a -> a) -> SectionArg a -> a #

toList :: SectionArg a -> [a] #

null :: SectionArg a -> Bool #

length :: SectionArg a -> Int #

elem :: Eq a => a -> SectionArg a -> Bool #

maximum :: Ord a => SectionArg a -> a #

minimum :: Ord a => SectionArg a -> a #

sum :: Num a => SectionArg a -> a #

product :: Num a => SectionArg a -> a #

Foldable1 SectionArg Source #

Since: 3.12.0.0

Instance details

Defined in Distribution.Fields.Field

Methods

fold1 :: Semigroup m => SectionArg m -> m #

foldMap1 :: Semigroup m => (a -> m) -> SectionArg a -> m #

foldMap1' :: Semigroup m => (a -> m) -> SectionArg a -> m #

toNonEmpty :: SectionArg a -> NonEmpty a #

maximum :: Ord a => SectionArg a -> a #

minimum :: Ord a => SectionArg a -> a #

head :: SectionArg a -> a #

last :: SectionArg a -> a #

foldrMap1 :: (a -> b) -> (a -> b -> b) -> SectionArg a -> b #

foldlMap1' :: (a -> b) -> (b -> a -> b) -> SectionArg a -> b #

foldlMap1 :: (a -> b) -> (b -> a -> b) -> SectionArg a -> b #

foldrMap1' :: (a -> b) -> (a -> b -> b) -> SectionArg a -> b #

Traversable SectionArg Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

traverse :: Applicative f => (a -> f b) -> SectionArg a -> f (SectionArg b) #

sequenceA :: Applicative f => SectionArg (f a) -> f (SectionArg a) #

mapM :: Monad m => (a -> m b) -> SectionArg a -> m (SectionArg b) #

sequence :: Monad m => SectionArg (m a) -> m (SectionArg a) #

Functor SectionArg Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

fmap :: (a -> b) -> SectionArg a -> SectionArg b #

(<$) :: a -> SectionArg b -> SectionArg a #

Show ann => Show (SectionArg ann) Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

showsPrec :: Int -> SectionArg ann -> ShowS #

show :: SectionArg ann -> String #

showList :: [SectionArg ann] -> ShowS #

Eq ann => Eq (SectionArg ann) Source # 
Instance details

Defined in Distribution.Fields.Field

Methods

(==) :: SectionArg ann -> SectionArg ann -> Bool #

(/=) :: SectionArg ann -> SectionArg ann -> Bool #

Ord ann => Ord (SectionArg ann) Source #

Since: 3.12.0.0

Instance details

Defined in Distribution.Fields.Field

Methods

compare :: SectionArg ann -> SectionArg ann -> Ordering #

(<) :: SectionArg ann -> SectionArg ann -> Bool #

(<=) :: SectionArg ann -> SectionArg ann -> Bool #

(>) :: SectionArg ann -> SectionArg ann -> Bool #

(>=) :: SectionArg ann -> SectionArg ann -> Bool #

max :: SectionArg ann -> SectionArg ann -> SectionArg ann #

min :: SectionArg ann -> SectionArg ann -> SectionArg ann #

Grammar and parsing

CabalStyleFile ::= SecElems

SecElems       ::= SecElem* '\n'?
SecElem        ::= '\n' SecElemLayout | SecElemBraces
SecElemLayout  ::= FieldLayout | FieldBraces | SectionLayout | SectionBraces
SecElemBraces  ::= FieldInline | FieldBraces |                 SectionBraces
FieldLayout    ::= name : line? ('\n' line)*
FieldBraces    ::= name : '\n'? '{' content '}'
FieldInline    ::= name : content
SectionLayout  ::= name arg* SecElems
SectionBraces  ::= name arg* '\n'? '{' SecElems '}'

and the same thing but left factored...

SecElems              ::= SecElem*
SecElem               ::= '\n' name SecElemLayout
                        |      name SecElemBraces
SecElemLayout         ::= :   FieldLayoutOrBraces
                        | arg*  SectionLayoutOrBraces
FieldLayoutOrBraces   ::= '\n'? '{' content '}'
                        | line? ('\n' line)*
SectionLayoutOrBraces ::= '\n'? '{' SecElems '\n'? '}'
                        | SecElems
SecElemBraces         ::= : FieldInlineOrBraces
                        | arg* '\n'? '{' SecElems '\n'? '}'
FieldInlineOrBraces   ::= '\n'? '{' content '}'
                        | content

Note how we have several productions with the sequence:

'\\n'? '{'

That is, an optional newline (and indent) followed by a { token. In the SectionLayoutOrBraces case you can see that this makes it not fully left factored (because SecElems can start with a \n). Fully left factoring here would be ugly, and though we could use a lookahead of two tokens to resolve the alternatives, we can't conveniently use Parsec's try here to get a lookahead of only two. So instead we deal with this case in the lexer by making a line where the first non-space is { lex as just the { token, without the usual indent token. Then in the parser we can resolve everything with just one token of lookahead and so without using try.

readFields :: ByteString -> Either ParseError [Field Position] Source #

Parse cabal style ByteString into list of Fields, i.e. the cabal AST.

readFields assumes that input ByteString is valid UTF8, specifically it doesn't validate that file is valid UTF8. Therefore bytestrings inside returned Field will be invalid as UTF8 if the input were.

>>> readFields "foo: \223"
Right [Field (Name (Position 1 1) "foo") [FieldLine (Position 1 6) "\223"]]

readFields won't (necessarily) fail on invalid UTF8 data, but the reported positions may be off.

You may get weird errors on non-UTF8 input, for example readFields will fail on latin1 encoded non-breaking space:

>>> isLeft (readFields "\xa0 foo: bar")
True

That is rejected because parser thinks \xa0 is a section name, and section arguments may not contain colon. If there are just latin1 non-breaking spaces, they become part of the name:

>>> readFields "\xa0\&foo: bar"
Right [Field (Name (Position 1 1) "\160foo") [FieldLine (Position 1 7) "bar"]]

The UTF8 non-breaking space is accepted as an indentation character (but warned about by readFields').

>>> readFields' "\xc2\xa0 foo: bar"
Right ([Field (Name (Position 1 3) "foo") [FieldLine (Position 1 8) "bar"]],[LexWarning LexWarningNBSP (Position 1 1)])

readFields' :: ByteString -> Either ParseError ([Field Position], [LexWarning]) Source #

Like readFields but also return lexer warnings.