Hello Paul,

As far as I can see you're calling the parens accessor function of the
TokenParser record instead of supplying a parser. Here is a working example
grammar I made for my bachelor paper a while ago:

module ExpressionsWithLexer where
import Text.ParserCombinators.Parsec.Expr
import Text.ParserCombinators.Parsec
import qualified Text.ParserCombinators.Parsec.Token as P
import Text.ParserCombinators.Parsec.Language


{-
Leftassociative: +, -, *, /
Rightassociative: ^
Priority 1: +,-
Priority 2: *, /
Priority 3: ^

expr   ::= factor (op factor)*
factor ::= number | '(' expr ')'

op     ::= '+' | '-' | '*' | '/' | '^'

number ::= ('0' | '1' | ... | '9')+
-}

lexer :: P.TokenParser ()
lexer = P.makeTokenParser
        (emptyDef
        { reservedOpNames = ["*","/","+","-", "^"]
        })

whiteSpace= P.whiteSpace lexer
natural = P.natural lexer
parens = P.parens lexer
reservedOp = P.reservedOp lexer

gram   = do  whiteSpace
             x <- expr
             eof
             return x

expr :: Parser Integer
expr = buildExpressionParser table factor
       <?> "expression"

-- Earlier in the list means a higher priority
table = [[op "^" (^) AssocRight]
        ,[op "*" (*) AssocLeft, op "/" div AssocLeft]
        ,[op "+" (+) AssocLeft, op "-" (-) AssocLeft]
        ]
       where op s f assoc = Infix (do{ reservedOp s; return f} <?>
"operator") assoc


factor = natural
         <|>
         (parens expr
          <?> "factor")

run :: Show a => Parser a -> String -> IO ()
run p input
       = case (parse p "" input) of
           Left err -> do{ putStr "parse error at "
                        ; print err
                        }
           Right x -> print x

exampleRun = run gram "(10 ^3 - (1 + 3))"


This grammar parses the EBNF like grammar included in the source.

As you can see parens is an accessor function of the TokenParser record. A
TokenParser record is thus produced by calling makeTokenParser and supplying
that function with a language definition. I used the emptyDef (empty
definition) as an argument for the makeTokenParser and only updated the
operatornames. After constructing a TokenParser parsers such as parens are
accessed by their accessor functions. For ease of use you can use a
qualified import for the token parser module and define the parens parser
and other parsers at toplevel like I did.

I only tested this with Parsec 2.1.0.1 but the idea should be the same. You
can read some more explanations and examples in my bachelor paper if you'd
like[1][2].

Good luck,

Bas van Gijzel

(server is currently down :( )
[1] Comparing Parser Construction Techniques:
http://referaat.cs.utwente.nl/new/papers.php?confid=12
[2] Parser Code:
http://fmt.cs.utwente.nl/~michaelw/projects/vgijzel/ParserCode.zip<http://fmt.cs.utwente.nl/%7Emichaelw/projects/vgijzel/ParserCode.zip>

On Sat, Jul 11, 2009 at 00:27, Paul Sujkov <[email protected]> wrote:

> Hi haskellers,
>
> I'm trying to use buildExpressionParser parser generator from ParsecExpr
> module of Parsec (
> http://legacy.cs.uu.nl/daan/download/parsec/parsec.html#ParsecExpr). It
> works well, except for the "parens" token parser (
> http://legacy.cs.uu.nl/daan/download/parsec/parsec.html#parens). This code
> (sample from Expressions part of the manual) typechecks fine:
>
> expr    :: Parser Integer
> expr    = buildExpressionParser table factor
>         <?> "expression"
>
> table   = [[op "*" (*) AssocLeft, op "/" div AssocLeft]
>           ,[op "+" (+) AssocLeft, op "-" (-) AssocLeft]
>           ]
>         where
>           op s f assoc
>              = Infix (do{ string s; return f}) assoc
>
>
> factor  = do{ char '('
>             ; x <- expr
>             ; char ')'
>             ; return x
>             }
>         <|> number
>         <?> "simple expression"
>
> but if I try to use parens:
>
> factor  = parens expr
>         <|> number
>         <?> "simple expression"
>
> it fails to typecheck:
>
> Couldn't match expected type `GenTokenParser s u m'
>            against inferred type `Parser Integer'
>     In the first argument of `parens', namely `expr'
>     In the first argument of `(<|>)', namely `parens expr'
>     In the first argument of `(<?>)', namely `parens expr <|> number'
> Failed, modules loaded: none.
>
> the type of expr infers to GenParser Char () Integer, and the expected type
> for the parens is GenTokenParser s u m (however, manual introduces it with
> the type CharParser st a expected)
>
> It seems pretty weird for me, as there are numerous examples of using
> parens with the buildExpressionParser (e.g.
> http://blog.moertel.com/articles/2005/08/27/power-parsing-with-haskell-and-parsec)
> and nobody comments such an error. I know I'm missing something very simple
> here, maybe someone could help me with it? Thanks in advace
>
> I'm using GHC 6.10.1 and Parsec 3.0.0
>
> --
> Regards, Paul Sujkov
>
> _______________________________________________
> Haskell-Cafe mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>

Attachment: ExpressionsWithLexer.hs
Description: Binary data

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to