ollef / Earley

Parsing all context-free grammars using Earley's algorithm in Haskell.
BSD 3-Clause "New" or "Revised" License
361 stars 24 forks source link

Is it okey to use "many" and heavily use Applicative parsing techniques? #55

Closed safinaskar closed 3 years ago

safinaskar commented 3 years ago

Is it normal to use Alternative's many? For example, x1 <- rule $ many x2? Is it normal to heavily use techniques known from Applicative parsing world, for example, to write something like the following code?

{-# LANGUAGE RecursiveDo #-}
import Control.Applicative
import Data.Char
import System.Environment
import Text.Earley

data Expr
  = Add Expr Expr
  | Mul Expr Expr
  | Var String
  deriving (Eq, Ord, Show)

sepBy :: Alternative f => f a -> f b -> f [b]
sepBy op x = (:) <$> x <*> many (op *> x)

expr :: Grammar r (Prod r String String Expr)
expr = mdo
  x1 <- rule $ foldl1 Add <$> sepBy (namedToken "+") (foldl1 Mul <$> sepBy (namedToken "*") ((Var <$> satisfy ident) <|> namedToken "(" *> x1 <* namedToken ")"))
  return x1
  where
    ident (x:_) = isAlpha x
    ident _     = False

main :: IO ()
main = do
  x:_ <- getArgs
  print $ fullParses (parser expr) $ words x

The code above is modified version of https://github.com/ollef/Earley/blob/e7de8b77b63e1ee889d98cb6dfc2994178f23e6d/examples/Expr.hs and I hope they are semantically equivalent. I tested my version and it works.

My question is not about performance. It is about semantics. I. e. is code above correct or it works simply by chance?

ollef commented 3 years ago

Yes, should be OK. There's special support to handle many, without which it would need to be implemented with a recursive rule.

safinaskar commented 3 years ago

Thanks. I just checked that hand-written many will not work (i. e. many2 x = ((:) <$> x <*> many2 x) <|> empty)