[Haskell-beginners] Parsing a file

David McBride toad3k at gmail.com
Wed Jan 26 17:29:40 UTC 2022


These two pieces of code are not equivalent.

  :{
     input = do
       eqatoms <- readFile "Parsing_File/eqatoms.out"
       return eqatoms
   :}

   :{
     main = do
       eqatoms <- readFile "Parsing_File/eqatoms.out"
       Parsec.parse species "test species" eqatoms
     return
   :}

You will have to do something like
  :{
     main = do
       eqatoms <- readFile "Parsing_File/eqatoms.out"
       let res = Parsec.parse species "test species" eqatoms
       putStrLn (show res)
     return
   :}

And you will eventually clean it up by using a case statement to
distinguish between success and error.

On Wed, Jan 26, 2022 at 7:41 AM Roger Mason <rmason at mun.ca> wrote:

> Hello,
>
> Warning: long post.
>
> I've worked my way through various parsing tutorials using either Parsec
> or ReadP.  I reached a point where I need to try parsing one of the
> types of file for which I'm writing the parser.  I have written parsers
> for various parts of this file:
>
> eqatoms.out:
> ======================================================
>
> Species :    1 (Si)
>  atom    1 is equivalent to atom(s)
>    1   2   3
>  atom    2 is equivalent to atom(s)
>    1   2   3
>  atom    3 is equivalent to atom(s)
>    1   2   3
>
> Species :    2 (O)
>  atom    1 is equivalent to atom(s)
>    1   2   3   4   5   6
>  atom    2 is equivalent to atom(s)
>    1   2   3   4   5   6
>  atom    3 is equivalent to atom(s)
>    1   2   3   4   5   6
>  atom    4 is equivalent to atom(s)
>    1   2   3   4   5   6
>  atom    5 is equivalent to atom(s)
>    1   2   3   4   5   6
>  atom    6 is equivalent to atom(s)
>    1   2   3   4   5   6
>
> ======================================================
>
> These are my imports:
> ======================================================
>   import qualified Text.Parsec as Parsec
>
>   import Text.Parsec ((<?>))
>
>   import Control.Applicative
>
>   import Control.Monad.Identity (Identity)
> ======================================================
>
> These are my parsers:
> ======================================================
>    :{
>     species :: Parsec.Parsec String () (String,String)
>     species = do
>      --Parsec.char 'S'
>      Parsec.string "Species"
>      Parsec.spaces
>      Parsec.char ':'
>      Parsec.spaces
>      digits <- Parsec.many1 Parsec.digit
>      Parsec.spaces
>      Parsec.char '('
>      id <- Parsec.many1 Parsec.letter
>      return (id,digits)
>    :}
>
>    :{
>     atom = do
>      Parsec.spaces
>      Parsec.string "atom"
>      Parsec.spaces
>      digits <- Parsec.digit
>      return digits
>    :}
>
> :{
>   equivalents = do
>    Parsec.spaces
>    digits <- Parsec.digit
>    return digits
> :}
> ======================================================
>
> Some simple tests:
> ======================================================
> src = "oops"
> Parsec.parse species src "Species :    1 (Si)"
>
> Right ("Si","1")
>
> src = "Parsing_File/eqatoms.out"
> Parsec.parse atom src "atom    5 is equivalent to atom(s)"
>
> Right '5'
>
> src = "Parsing_File/eqatoms.out"
> Parsec.parse (Parsec.many1 equivalents) src "   1   2   3   4   5   6"
>
> : Right "123456"
> ======================================================
>
> So, the individual parsers work as intended.  However, parsing an actual
> file does not work.
>
> I define a function to return the file contents:
> ======================================================
>    :{
>      input = do
>        eqatoms <- readFile "Parsing_File/eqatoms.out"
>        return eqatoms
>    :}
> ======================================================
>
> A test shows that my reader works:
> ======================================================
> input
>
> : Species :    1 (Si)\n atom    1 is equivalent to atom(s)\n   1   2
> 3\n atom    2 is equivalent to atom(s)\n   1   2   3\n atom    3 is
> equivalent to atom(s)\n   1   2   3\n\nSpecies :    2 (O)\n atom    1 is
> equivalent to atom(s)\n   1   2   3   4   5   6\n atom    2 is
> equivalent to atom(s)\n   1   2   3   4   5   6\n atom    3 is
> equivalent to atom(s)\n   1   2   3   4   5   6\n atom    4 is
> equivalent to atom(s)\n   1   2   3   4   5   6\n atom    5 is
> equivalent to atom(s)\n   1   2   3   4   5   6\n atom    6 is
> equivalent to atom(s)\n   1   2   3   4   5   6\n
>
> ======================================================
>
> I attempt to parse the input:
> ======================================================
>    :{
>      main = do
>      eqatoms <- readFile "Parsing_File/eqatoms.out"
>      Parsec.parse species "test species" eqatoms
>      return
>    :}
>
> Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity|
> Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity|
> Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity|
> Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity|
> Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity|
> <interactive>:250:3: error:
>     ,* Couldn't match type `Either Parsec.ParseError' with `IO'
>       Expected type: IO (String, String)
>         Actual type: Either Parsec.ParseError (String, String)
>     ,* In a stmt of a 'do' block:
>         Parsec.parse species "test species" eqatoms
>       In the expression:
>         do eqatoms <- readFile "Parsing_File/eqatoms.out"
>            Parsec.parse species "test species" eqatoms
>            return
>       In an equation for `main':
>           main
>             = do eqatoms <- readFile "Parsing_File/eqatoms.out"
>                  Parsec.parse species "test species" eqatoms
>                  return
>
> <interactive>:251:3: error:
>     ,* Couldn't match expected type `IO b'
>                   with actual type `a0 -> m0 a0'
>     ,* Probable cause: `return' is applied to too few arguments
>       In a stmt of a 'do' block: return
>       In the expression:
>         do eqatoms <- readFile "Parsing_File/eqatoms.out"
>            Parsec.parse species "test species" eqatoms
>            return
>       In an equation for `main':
>           main
>             = do eqatoms <- readFile "Parsing_File/eqatoms.out"
>                  Parsec.parse species "test species" eqatoms
>                  return
>     ,* Relevant bindings include
>         main :: IO b (bound at <interactive>:248:3)
> ======================================================
>
> Can someone please help me to get this to work?
>
> Thanks for reading to the end of this very long post.
> Roger
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20220126/88629188/attachment-0001.html>


More information about the Beginners mailing list