使用buildExpressionParser时Parsec挂起

时间:2014-08-12 11:09:39

标签: haskell parsec

我正在尝试使用Parsec为数学方程创建一个基本解析器,我在使用buildExpressionParser函数时遇到了一些麻烦。

我已经创建了一个parsecParse函数,但是当我在ghci:parse parsecParse "" "200*6"中调用它时它会永远挂起。我无法弄清楚为什么。有什么想法吗?

module Equation where

import Control.Applicative hiding (many, (<|>))

import Text.Parsec.Char (char, digit)
import Text.Parsec.Combinator (many1, option)
import Text.Parsec.Expr (Assoc (..), Operator (..), buildExpressionParser)
import Text.Parsec.Prim ((<|>), try)
import Text.Parsec.String (Parser)

data Equation = Leaf Double | Tree Op Equation Equation deriving (Show)
data Op = Plus | Minus | Multiply | Divide deriving (Show)

parsecParse :: Parser Equation
parsecParse = try parseOperator <|> parseDouble

parseDouble :: Parser Equation
parseDouble = fmap (Leaf . read) $ (++) <$> integer <*> fraction
    where integer  = many1 digit
          fraction = option "" $ (:) <$> char '.' <*> many1 digit

parseOperator :: Parser Equation
parseOperator = buildExpressionParser table parsecParse
    where table     = [[ getOp '*' Multiply, getOp '/' Divide ],
                       [ getOp '+' Plus,     getOp '-' Minus ]]
          getOp c o = Infix (char c >> return (Tree o)) AssocLeft

1 个答案:

答案 0 :(得分:3)

你遇到了问题,因为parseOperator在最左边的位置重复自身,这是Parsec无法直接处理的,并且它提供了无限的递归。

buildExpressionParser的最后一个参数应该是一个解析更多“基本”元素的解析器。

可以间接递归parseOperator,例如处理带括号的元素,但,使它最终位于自身最左边的位置。