1
votes

I am learning parsec with the example https://github.com/JakeWheat/intro_to_parsing

As the code blow, the result is always "right"

Anyone kindly give me some tips?

*Main> regularParse  parser4search "a"  
Loading package array-0.5.0.0 ... linking ... done.  
Loading package deepseq-1.3.0.2 ... linking ... done.  
Loading package bytestring-0.10.4.0 ... linking ... done.  
Loading package text-1.1.0.0 ... linking ... done.  
Loading package transformers-0.3.0.0 ... linking ... done.  
Loading package mtl-2.1.3.1 ... linking ... done.  
Loading package parsec-3.1.7 ... linking ... done.  
Right (Num *** Exception: Prelude.read: no parse  
*Main> regularParse  parser4search "1"  
Right (Num 1)  

=================

import Text.Parsec (parse,anyChar)
import Text.Parsec.String --(Parser)
import Text.Parsec.Char (oneOf, char, digit, satisfy,letter)
import Text.Parsec.Combinator (many1, choice, chainl1)
import Control.Applicative ((<|>), many)
import Control.Monad --(void)
import Data.Char --(isLetter, isDigit)


data SimpleExpr = Num Integer
             | Var String
             | Add SimpleExpr SimpleExpr
             | Parens SimpleExpr
             | Str [Char]
               deriving (Eq,Show)

regularParse p = parse p ""

parser4search:: Parser SimpleExpr
parser4search = do
    searchStr <- many digit
    return (Num (read searchStr))
2

2 Answers

3
votes

many means parse zero or more items.

many1 means parse one or more items.

So, many digit succeeds with input "1", "24", or "".

many1 succeeds with input "1", "24", but fails with "". It sounds like this is what you want.

You also might want to look at eof so that trailing unparsed stuff will not be allowed.

1
votes

The parsec does not give error (left value) because there is no error in parsing "a". the many digit statement returns an empty string in case it does not find any integer characters. To make your code work you need to handle the empty string. For eg.

parser4search:: Parser SimpleExpr
parser4search = do
    searchStr <- many digit
    if searchStr == [] 
    then return (Num 0) 
    else return (Num (read searchStr))