shmish111
shmish111

Reputation: 3797

Parsec something like many1 but fail if ends

I'm going through Write Yourself a Scheme in 48 Hours and I'm stuck on getting numbers to work properly. I want the following to parse a hex number

parseOct :: Parser LispVal
parseOct = do
        char '#'
        char 'o'
        x <- many1 $ oneOf "01234567"
        return . Number . fst . head . readOct $ x

This works if I give it #o7 for example and gives me 7 as expected however it doesn't fail if I give it #o78 instead it gives me 7. It seems this is because of many1 which disregards anything once it doesn't match. Is there anything in Parsec that will enable me to get all the oct numbers but fail if it ever gets a non-oct character such as 8?

Upvotes: 0

Views: 132

Answers (1)

ErikR
ErikR

Reputation: 52039

Use notFollowedBy to make sure no alpha-numerics follow the octal digits:

import Text.Parsec
import Text.Parsec.Char
import Text.Parsec.String
import Text.Parsec.Combinator

parseOct' :: Parser String
parseOct' = do 
  char '#'
  char 'o'
  x <- many1 (oneOf "01234567")
  notFollowedBy alphaNum
  return x

test1 = parseTest parseOct' "#o123"
test2 = parseTest parseOct' "#o1238"

E.g.:

*Main> test1
"123"
*Main> test2
parse error at (line 1, column 7):
unexpected '8'

Upvotes: 2

Related Questions