
Hi, I’m using Parsec to parse structured text and have some problems with mandatory and optional text entries and the order in which they occur. For example module{ name = some string source = … dest = ….. bundle = … bundle_dest = … zip_name = …. } In the above text the name and source are mandatory and all others are optional. I’m not quite sure how to handle the optional parts once I’ve parsed name and source. Should I enforce the rule that if dest does appear then it must be first in the list? In this situation how should I make use of the various Parsec functions such as choice, option, optionMaybe, lookAhead etc. Thanks Mike

On Sun, Mar 06, 2016 at 09:26:17AM +0000, Mike Houghton wrote:
Hi, I’m using Parsec to parse structured text and have some problems with mandatory and optional text entries and the order in which they occur. For example:
module{
name = some string source = …
dest = ….. bundle = … bundle_dest = … zip_name = ….
}
Hello Mike, I would personally keep it simple. Parse the (item, value) list and after that check if it is well formed (i.e. contains 'name' and 'source' values). If not, call `parserFail` with an appropriate message.

Hi Francesco, Quick response! Thanks. I see, so would it reduce to something like? many itemValue and originally I was thinking the data structure that it would parse into would be data Module = Module {— some record structure—} but now it would be roughly like… type Entry = (String, String) data Module = Module [Entry] Thanks
On 6 Mar 2016, at 09:30, Francesco Ariis
wrote: On Sun, Mar 06, 2016 at 09:26:17AM +0000, Mike Houghton wrote:
Hi, I’m using Parsec to parse structured text and have some problems with mandatory and optional text entries and the order in which they occur. For example:
module{
name = some string source = …
dest = ….. bundle = … bundle_dest = … zip_name = ….
}
Hello Mike, I would personally keep it simple. Parse the (item, value) list and after that check if it is well formed (i.e. contains 'name' and 'source' values). If not, call `parserFail` with an appropriate message. _______________________________________________ Beginners mailing list Beginners@haskell.org mailto:Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

On Sun, Mar 06, 2016 at 09:54:34AM +0000, Mike Houghton wrote:
Hi Francesco, Quick response! Thanks.
I see, so would it reduce to something like? many itemValue
and originally I was thinking the data structure that it would parse into would be
data Module = Module {— some record structure—}
but now it would be roughly like…
type Entry = (String, String)
data Module = Module [Entry]
Thanks
Yes, it would lead to some kind of (YourType, String) association list. If you are more interested in a datatype with records I see two ways of achieving it: a. a function `[(YrType, String)] -> RecordsData` (not so pretty but doable, also you can check for well-formedness here) (Using a sum type YrType is in my opinion better than plain Strings as it catches some more errors at compile time). b. directly via parsing, using `optionMaybe` and glue. Depending on how your input is structured this may or may not be more hairy (can name and source appear after an optional tag? What about duplicated tags? etc.). In its simplest form you can use a succinct applicative-style, but the castle crumbles if want more. See which fits better (I suspect a.), play with it and report back; parsing has never been an elegant business!

Hi Francesco, This is really helpful - thank you. I’m neutral about using a record - it is just how I’d done other simple parsers before. Using a list of tuples seems to simplify the parsing but then the ‘hit’ comes on converting to a record. However, this has made me question the necessity of a record, I suspect the processing subsequent to parsing can be better achieved by mapping over the list. Thanks
On 6 Mar 2016, at 10:17, Francesco Ariis
wrote: On Sun, Mar 06, 2016 at 09:54:34AM +0000, Mike Houghton wrote:
Hi Francesco, Quick response! Thanks.
I see, so would it reduce to something like? many itemValue
and originally I was thinking the data structure that it would parse into would be
data Module = Module {— some record structure—}
but now it would be roughly like…
type Entry = (String, String)
data Module = Module [Entry]
Thanks
Yes, it would lead to some kind of (YourType, String) association list. If you are more interested in a datatype with records I see two ways of achieving it:
a. a function `[(YrType, String)] -> RecordsData` (not so pretty but doable, also you can check for well-formedness here) (Using a sum type YrType is in my opinion better than plain Strings as it catches some more errors at compile time).
b. directly via parsing, using `optionMaybe` and glue. Depending on how your input is structured this may or may not be more hairy (can name and source appear after an optional tag? What about duplicated tags? etc.). In its simplest form you can use a succinct applicative-style, but the castle crumbles if want more.
See which fits better (I suspect a.), play with it and report back; parsing has never been an elegant business!
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Hi, Just to recap I wanted to parse name:value pairs where some pairs are mandatory and some are not. eg //these are mandatory location : /user/local target : /x/y //these are optional copyTo : /a/b trace : bla blah ,,, undo : etc etc so I made data Item = Item (Name, Value) deriving (Show) where Name, Value are strings and made a parser for it. -- KeyWordItemParser kwip :: String -> Parser Item kwip keyWord = do spaces name <- string keyWord spaces char ':' spaces val <- itemValue spaces return $ Item (name, val) I made the mandatory of fixed order and hence easy to parse. For the optional I ended up defining a fixed order in which they can appear if indeed they do appear. So, for example, ‘copyTo' has to come before ‘trace’ This allowed code like many $ kwip “copyTo" many $ kwip “trace" many $ kwip “undo" which of course may result in duplicates that are later flagged as errors in post parsing validation. This validation step was needed anyway for other checking so a bit more was sort of ok. Pragmatically speaking It works ok but I’m not really happy with it. I’d really like to not have to enforce order. What I have been considering but have not yet been able to articulate in Haskell is, for parsing the optionals in any order, is to create a list of parsers and apply whilst removing parsers from the list. i.e. in pseudo code… Try to parse A : w B : x C : y D : z in any order parserList = [kwip A, kwip B, kwip C, kwip D] parse list text = do parserList empty? then done try a parser from parserList until one works - if none work then done (or error) if one worked accumulate result remove succesful parser from parserList then call again Any advice on how to write this in Haskell would be appreciated. Many thanks Mike
On 6 Mar 2016, at 10:17, Francesco Ariis
wrote: On Sun, Mar 06, 2016 at 09:54:34AM +0000, Mike Houghton wrote:
Hi Francesco, Quick response! Thanks.
I see, so would it reduce to something like? many itemValue
and originally I was thinking the data structure that it would parse into would be
data Module = Module {— some record structure—}
but now it would be roughly like…
type Entry = (String, String)
data Module = Module [Entry]
Thanks
Yes, it would lead to some kind of (YourType, String) association list. If you are more interested in a datatype with records I see two ways of achieving it:
a. a function `[(YrType, String)] -> RecordsData` (not so pretty but doable, also you can check for well-formedness here) (Using a sum type YrType is in my opinion better than plain Strings as it catches some more errors at compile time).
b. directly via parsing, using `optionMaybe` and glue. Depending on how your input is structured this may or may not be more hairy (can name and source appear after an optional tag? What about duplicated tags? etc.). In its simplest form you can use a succinct applicative-style, but the castle crumbles if want more.
See which fits better (I suspect a.), play with it and report back; parsing has never been an elegant business!
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (2)
-
Francesco Ariis
-
Mike Houghton