2014-04-07 94 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使用運算符的表中,給它一個高優先級。