j-mie6 / design-patterns-for-parser-combinators

A Really Cool Calculator written in Haskell... or is it?
BSD 3-Clause "New" or "Revised" License
41 stars 1 forks source link

Parser combinators design patterns versus parsley Haskell 2.0.0.0 #9

Closed funarog closed 1 year ago

funarog commented 1 year ago

I am having trouble implementing recommended parser combinator design patterns using parsley 2.0.0.0 An implementation of a simple Expr function using design pattern for white space and yields a build error. Can't find a solution in any Parsley documentation.

The code compiles if function comments are removed

Design pattern:

whitespace :: Parser ()
whitespace = void (many (satisfy isSpace))

lexeme :: Parser a -> Parser a
lexeme p = p <* whitespace` 

function:

expr :: Parsley.Parser Expr
expr = whitespace *> sum' <* eof
    where
        -- whitespace = skipMany (oneOf " \n")
        -- lexeme p = p <* whitespace
        operator op = lexeme $ string op

        digit =
            QQ (\c -> fromIntegral (ord c - ord '0'))
                <$> oneOf "0123456789"
        number = lexeme $ QQ (Num) <$> somel (QQ (\q r -> 10 * q + r)) (LIFTED 0) digit

        atom = lexeme (char '(') *> sum' <* lexeme (char ')') <|> number
        sum' =
            precHomo
                atom
                [ ops
                    InfixL
                    [ operator "*" $> QQ (Bin Mul)
                    , operator "/" $> QQ (Bin Div)
                    ]
                , ops
                    InfixL
                    [ operator "+" $> QQ (Bin Add)
                    , operator "-" $> QQ (Bin Sub)
                    ]
                ]

Build profile: -w ghc-9.2.7 -O1

src/Parser.hs:61:26: error: • Couldn't match type ‘(->) Char’ with ‘Defunc’ arising from a use of ‘satisfy’ • In the first argument of ‘many’, namely ‘(satisfy isSpace)’ In the first argument of ‘void’, namely ‘(many (satisfy isSpace))’ In the expression: void (many (satisfy isSpace)) | 61 | whitespace = void (many (satisfy isSpace))

Imports


{-# LANGUAGE CPP #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE LambdaCase #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Unused LANGUAGE pragma" #-}
{-# HLINT ignore "Redundant bracket" #-}

#define QQ(x) (makeQ (x) [|| (x) ||])

'''
j-mie6 commented 1 year ago

QQ(isSpace)!

j-mie6 commented 1 year ago

As a side note, when I finally get some time to deal with my huge backlog, I do intend to write a proper wiki/tutorial for parsley Haskell. And bring more of the "proper" API in from Scala parsley. We can do a lot better.

funarog commented 1 year ago

Well that worked! Thanks.

I am currently working with haskell-parsing-benchmarks to try and determine if the claim that flatparse is the fastest haskell parser is true. I suspect that one is comparing apples with oranges. Nonetheless "[when [you] get some time ..." and "write a proper wiki/tutorial for parsley.: That would be great. This gives me an idea to perhaps benchmark Scala parsley.