Monadic parse with uu-parsinglib

237 Views Asked by At

I'm trying to create a Monadic parser using uu_parsinglib. I thought I had it covered, but I'm getting some unexpected results in testing

A cut down example of my parser is:

pType :: Parser ASTType
pType = addLength 0 $
  do (Amb n_list) <- pName
     let r_list = filter attributeFilter n_list
     case r_list of
        (ASTName_IdName a : [] )   -> return (ASTType a)
        (ASTName_TypeName a : [] ) -> return (ASTType a)
        _                          -> pFail
     where nameFilter :: ASTName' -> Bool
           nameFilter a =
              case a of
                 (ASTName_IDName _)   -> True
                 (ASTName_TypeName _) -> True
                 _                    -> False

data ASTType  = ASTType ASTName

data ASTName  = Amb [ASTName']

data ASTName' =
   ASTName_IDName     ASTName
   ASTName_TypeName   ASTName
   ASTName_OtherName  ASTName
   ASTName_Simple     String

pName is an ambiguous parser. What I want type parser to do is apply a post filter, and return all alternatives that satisfy nameFilter, wrapped as ASTType.

If there are none, it should fail.

(I realise the example I've given will fail if there is more than one valid match in the list, but the example serves its purpose)

Now, this all works as far as I can see. The problem lies when you use it in more complicated Grammars, where odd matches seem to occur. What I suspect is the problem is the addLength 0 part

What I would like to do is separate out the monadic and applicative parts. Create a monadic parser with the filtering component, and then apply pName using the <**> operator.

Alternatively

I'd settle for a really good explanation of what addLength is doing.

1

There are 1 best solutions below

0
On

I've put together a fudge/workaround to use for monadic parsing with uu-parsinglib. The only way I ever use Monadic parsers is to analysis a overly generous initial parser, and selectively fail its results.

bind' :: Parser a -> (a -> Parser b) -> Parser b
bind' a@(P _ _ _ l') b = let (P t nep e _) = (a >>= b) in P t nep e l'

The important thing to remember when using this parser is that

a -> M b

must consume no input. It must either return a transformed version of a, or fail.

WARNING

Testing on this is only minimal currently, and its behaviour is not enforced by type. It is a fudge.