[Haskell-cafe] Re: parsebinaryoperations

Ben Franksen ben.franksen at online.de
Thu Dec 13 16:35:39 EST 2007

Ryan Bloor wrote:
> I have a function parseInt... which needs an error guard for when the
> input is not an Int.
> parseInt :: ParserparseInt [] = []parseInt xs = let (digits, rest) = span
> isDigit (removeSpace xs)                in [(EInt (read digits),
> removeSpace rest)]

This is how your source code happens to be rendered on my mail client. This
part of your mail is the reason:

> --===============0328857386==
> Content-Type: multipart/alternative;
>       boundary="_4752b91d-a167-4274-af0a-1982e53bc6c0_"
> --_4752b91d-a167-4274-af0a-1982e53bc6c0_
> Content-Type: text/plain; charset="Windows-1252"
> Content-Transfer-Encoding: quoted-printable

This encoding (charset="Windows-1252") is not available on my system. It
would help others to read your message (leading to more responses to your
question and thus better help) if you could configure your mail program to
use a more widely understood encoding, for instance utf-8, or latin-1.

> Also... I have a function that does this... parseBinaryOp "+" "(5 + 2) if"
>      gives...[(Int 5, Int 2, "if")] so, op is '+' or "&&". I am unsure of
> how to begin...
> parseBinaryOp :: String -> String -> [(Expr, Expr, String)]parseBinaryOp
> op str
> Thankyou
> Ryan

Thank you, too, for respecting mailing list netiquette :-))

Now to your question: Since Haskell is pure, you need to encode possible
parse failure into the result type of your parsing function, like this:

  data Result = Success Expr
              | Failure String

where the 'Expr' above is the type you want to get back on a successful
parse, and the type argument 'String' to the 'Failure' constructor is for
error messages. 

Your parseExpr function could then have a type like

  type Parser = String -> ParseResult Expr

which could be called (from main) thus

  case parseExpr input of
    Success expr -> print expr
    Failure err_msg  -> putStrLn $ "parse error: " ++ err_msg

Another good idea, instead of just collecting a list (in fact, a tuple) of
tokens as you did above, is to design 'Expr' so that it can represent a
complete parse _tree_. Since usually expressions can be nested arbitrarily
deep, any finite type won't do, you need a recursive type. For example

  data BinOp = OpPlus | OpMinus | OpMult
  -- enumerating all possible operators is more type safe than using String

  -- an expression is...
  Expr = EInt Integer           -- either a literal integer
       | EBinOp BinOp Expr Expr -- or two expressions combined with a binary

Hope this helps.


More information about the Haskell-Cafe mailing list