Using Parsec to parse regular expressions

后端 未结 2 923
情深已故
情深已故 2021-02-08 23:09

I\'m trying to learn Parsec by implementing a small regular expression parser. In BNF, my grammar looks something like:

EXP  : EXP *
     | LIT EXP
     | LIT
         


        
2条回答
  •  无人及你
    2021-02-08 23:32

    Your grammar is left-recursive, which doesn’t play nice with try, as Parsec will repeatedly backtrack. There are a few ways around this. Probably the simplest is just making the * optional in another rule:

    lit :: Parser (Char, Maybe Char)
    lit = do
      c <- noneOf "*"
      s <- optionMaybe $ char '*'
      return (c, s)
    

    Of course, you’ll probably end up wrapping things in a data type anyway, and there are a lot of ways to go about it. Here’s one, off the top of my head:

    import Control.Applicative ((<$>))
    
    data Term = Literal Char
              | Sequence [Term]
              | Star Term
    
    expr :: Parser Term
    expr = Sequence <$> many term
    
    term :: Parser Term
    term = do
      c <- lit
      s <- optionMaybe $ char '*' -- Easily extended for +, ?, etc.
      return $ if isNothing s
        then Literal c
        else Star $ Literal c
    

    Maybe a more experienced Haskeller will come along with a better solution.

提交回复
热议问题