Parsing 如何在Haskell中用Parsec隐式乘法解析表达式
我有一个允许隐式乘法的语法,Parsing 如何在Haskell中用Parsec隐式乘法解析表达式,parsing,haskell,parsec,Parsing,Haskell,Parsec,我有一个允许隐式乘法的语法,(1+2)(3+4)与(1+2)*(3+4)或(1+2)7与(1+2)*7 如何在Haskell中实现这一点?以下是我到目前为止的情况: import Control.Monad import Text.ParserCombinators.Parsec import Text.ParserCombinators.Parsec.Expr import Text.ParserCombinators.Parsec.Language import qualified Text
(1+2)(3+4)
与(1+2)*(3+4)
或(1+2)7
与(1+2)*7
如何在Haskell中实现这一点?以下是我到目前为止的情况:
import Control.Monad
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Expr
import Text.ParserCombinators.Parsec.Language
import qualified Text.ParserCombinators.Parsec.Token as Token
languageDef =
emptyDef { Token.identStart = letter
, Token.identLetter = alphaNum
, Token.reservedOpNames = ["+", "*"]
}
lexer = Token.makeTokenParser languageDef
reservedOp = Token.reservedOp lexer
parens = Token.parens lexer
integer = Token.integer lexer
data Expr = Const Int
| Binary BinOp Expr Expr
deriving (Show)
data BinOp = Add | Multiply
deriving (Show)
expression = buildExpressionParser operators term
operators = [ [Infix (reservedOp "*" >> return (Binary Multiply)) AssocLeft]
, [Infix (reservedOp "+" >> return (Binary Add )) AssocLeft]
]
term = liftM (Const . fromIntegral) integer
<|> parens expression
<|> (do e1 <- expression
e2 <- term
return $ Binary Multiply e1 e2)
parseString str =
case parse expression "" str of
Left e -> error $ show e
Right r -> r
import-Control.Monad
导入Text.ParserCombinators.Parsec
导入Text.ParserCombinators.Parsec.Expr
导入Text.ParserCombinators.Parsec.Language
导入限定的Text.ParserCombinators.Parsec.Token作为令牌
语言定义=
emptyDef{Token.identStart=字母
,Token.identLetter=alphaNum
,Token.reservedOpNames=[“+”,“*”]
}
lexer=Token.makeTokenParser languageDef
reservedOp=Token.reservedOp lexer
parens=令牌。parens lexer
integer=Token.integer lexer
数据表达式=常数Int
|二进制二进制二进制表达式
派生(显示)
数据BinOp=加|乘
派生(显示)
expression=buildExpressionParser运算符术语
运算符=[[Infix(reservedOp“*”>>返回(二进制乘法))AssocLeft]
,[Infix(reservedOp“+”>>返回(二进制添加))AssocLeft]
]
term=liftM(常量fromIntegral)整数
帕伦斯表达式
(不知道)
但它不起作用,我在解析时出错,当我尝试解析
((1+5)8)
时,我遇到了意外的“8”期望运算符或“
,除非你对makeTokenParser
背后的机制有一个很好的理由,否则这似乎有点过头了。通常,当您有一种与现有语言非常相似的语言,或者您有许多不同级别的运算符优先级时,这非常有用。在您的情况下,您可以在几行中编写表达式
import Text.Parsec.String (Parser)
import Text.Parsec
import Control.Applicative (some)
-- ...
expression :: Parser Expr
expression = sum
where
product = foldl1 (Binary Multiply) <$> factor `sepBy1` optional (char '*')
sum = foldl1 (Binary Add) <$> product `sepBy1` char '+'
factor = int <|> between (char '(') (char ')') expression
int = Const . read <$> some digit
-- ...
您能确保您的示例中包含所有导入吗?如果我们必须弄清楚您导入的所有内容,那就有点麻烦了…@Alec我已经添加了所有缺少的部分,以便代码能够编译和工作。您是否尝试将运算符定义从
reservedOp“*”
更改为reservedOp“*”空格
?@BenjaminHodgson这导致了无限递归。我想我需要改变一下术语,但我不明白你是怎么想出解决办法的?我遇到了一个类似的问题。谢谢,它工作得很好,但实际上我需要其他运算符和运算符优先级,还有二进制的-
,/
和^
,我删除了它们以缩短示例代码,这实际上是我使用BinOp
类型的原因
ghci> parseString "1+2*3"
Binary Add (Const 1) (Binary Multiply (Const 2) (Const 3))
ghci> parseString "(1+2)(3+4)"
Binary Multiply (Binary Add (Const 1) (Const 2)) (Binary Add (Const 3) (Const 4))
ghci> parseString "(1+2)*(3+4)"
Binary Multiply (Binary Add (Const 1) (Const 2)) (Binary Add (Const 3) (Const 4))
ghci> parseString "(1+2)7"
Binary Multiply (Binary Add (Const 1) (Const 2)) (Const 7)
ghci> parseString "(1+2)*7"
Binary Multiply (Binary Add (Const 1) (Const 2)) (Const 7)