2014-04-07 63 views
2

解析功能应用我试图解析般的表情下面用秒差距:用秒差距

f a b c 
=> (Appl (Appl (Appl f a) b) c) 

我试着用线沿线的东西:

appl :: Parser Expr 
appl = do 
    f <- expr 
    gs <- many expr 
    return $ foldr (\x y -> Appl x y) f gs 

但我被陷在一个无限循环。 expr是一个函数,它解析所有可能的 表达式,包括通过创建词法分析器(特别是使用Parsec.Token.makeTokenParser)获得的空白。

我想知道是否有一些简单的方法来做到这一点,或者其他建议如何解决这个问题。我曾考虑尝试使用Parsec.Expr,但我不确定如何将空间用作操作员。

感谢您的帮助!

+2

不包括'expr'和'Expr'的定义,所以很难说真正发生了什么。你应该添加这些,也是一个样本输入和样本输出。乍一看,假设'expr'不消耗空白,你需要像'sepBy expr spaces'这样的东西,它将解析由空格分隔的'expr'。 – user2407038

+0

我在expr上有一点评论,因为它使用从词法分析器获得的令牌,所以它消耗了空格 – user3505407

+3

请包含更多的语法。 'expr'解析器是否也解析'Appl'?如果是,那么这里是[左递归](http://en.wikipedia.org/wiki/Left_recursion)的例子。 –

回答

2

正如你所建议的,一种解决方案是将空间视为二元运算符。首先,为函数应用程序定义一个解析器。

spacef :: Parser() 
spacef = whiteSpace 
     *> notFollowedBy (choice . map reservedOp $ opNames) 
     >> return Appl 

这里reservedOp是保留操作符的解析器,opNames是这些名称的列表。现在,让这个操作在你的语法

functionOp :: Operator String() Identity Expr 
functionOp = Infix spacef AssocLeft 

,并添加functionOp你,你有buildExpressionParser使用运算符的表中,给它一个高优先级。