我正在尝试使用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
答案 0 :(得分:3)
你遇到了问题,因为parseOperator
在最左边的位置重复自身,这是Parsec无法直接处理的,并且它提供了无限的递归。
buildExpressionParser
的最后一个参数应该是一个解析更多“基本”元素的解析器。
可以间接递归parseOperator
,例如处理带括号的元素,但不,使它最终位于自身最左边的位置。