Learning Haskell Parsec and dealing with optional Parsers -
i'm redoing old homework assignment fun learn how use parsec , i'm having trouble structuring parsers exits (and included datatype). first file list of rooms. each room contains room name (below -- room --), description or story , list of exits in format of (direction, destination)
. person choose direction , you'd room name , bring player next room.
-- room -- center in square room. there doors north, south, east, , west. -- exits -- north: north hall south: south room east: east room west: west room -- room -- north hall in hallway. there doors north , south.
as can see rooms have no exits (nothing how i'm storing it). there maybe exits.
i have gotten far exits part , parsers before step seem work. problem handling fact there no exits or more 1 exit. how handle exits think affects how handle exits types (aka type exits might become maybe [ exit ]
anyway here code:
--module loader -- game parser go here -- import text.parsercombinators.parsec import data.list.split astory = unlines [" -- room --", "cell", "you have been locked in dungeon cell. prisoner next", "to whipsers, there's tunnel behind bed on the", "south wall. luck!", "-- exits --", "south: tunnel"] type rooms = [room] type story = string type destination = string data exit = exit { direction :: direction, destination :: destination } deriving (ord, show, eq) type exits = [ exit ] data room = room { name :: string , story :: string , exits :: exits } deriving (ord, show, eq) data direction = nothing | north | south | east | west | quit deriving (ord, show, eq) an_exit = "north: tunnel \n" a_full_exit = "-- exits --\nsouth: tunnel" directionparser :: parser direction directionparser = (string "south:" >> return south) <|> (string "north:" >> return north) <|> (string "east:" >> return east) <|> (string "west:" >> return west) parseexit :: parser exit parseexit = direction <- directionparser spaces destination <- many (noneof "\n") return $ exit direction destination parseexits :: parse exits parseexits = string "-- exits --\n" --oneroom :: parser room --oneroom = -- string "--room--\n" -- name <- many (noneof "\n") -- newline -- story <- manytill anychar (string "-- exits --") -- optionmaybe (string "-- exits --") -- exits <- optionmaybe $ many1 anyexits -- return $ room name story exits --main = -- file <- readfile "cave.adventure" -- let stories = spliton "\n\n" file -- mapm putstrln stories
i commented out room testing smaller parsers.
my approach:
- make parseexits parses -- exits -- , "many of parseexit".
- if --exit-- isn't found parser fails (i think returns nothing then)
- in oneroom parser 0 or many parseexits or eof (since i'm pre splitting on \n\n)
questions:
- how do none or many according parsec docs optionmaybe or optional trick applied ? in exits or 1 room ? the docs easy access
- is approach of dealing mini parsers correct way deal problem in haskell , parsec?
- finally oneroom receives file strings split on \n\n think can include in parser last line of oneroom parser correct ?
- in oneroom parser i'm parsing story element ends @ -- exit -- i'm not convinced story doesn't consume next -- exits -- or eof? how story parser end @ either first -- exits -- finds or eof(or \n\n if parse full file)
i hope questions , code clear enough if not please let me know how can clarify. in advance.
i don't want write whole parser you, i'm trying answer individual questions.
- how do none or many [...]
just use many
instead of many1
.
to make whole "-- exits --" block optional, can try like
exits <- parseexists <|> return []
- is approach of dealing mini parsers correct way deal problem in haskell , parsec?
yes. rule of thumb, try write @ least 1 parser every datatype, more.
- finally oneroom receives file strings split on \n\n think can include in parser last line of oneroom parser correct?
i think shouldn't use split
in main
function instead use newline
in parsers wherever want have newline character.
- in oneroom parser i'm parsing story element ends @ -- exit -- i'm not convinced story doesn't consume next -- exits -- or eof? how story parser end @ either first -- exits -- finds or eof(or \n\n if parse full file)
maybe want following:
-- succeeds if we're @ end of story -- never consumes input endofstory :: parser () endofstory = lookahead $ try (string "-- room --" >> newline) <|> try (string "-- exits --" >> newline) <|> try (newline >> newline) <|> eof
with function this, use manytill ... endofstory
.
Comments
Post a Comment