我有一个允许隐式乘法的语法,(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
但它不起作用,我在解析时出错,当我尝试解析((1 + 5) 8)
时我有unexpected "8" expecting operator or ")"
答案 0 :(得分:1)
除非你有充分的理由支持makeTokenParser
背后的机制,否则看起来有点矫枉过正。通常,当您的语言与现有语言非常相似,或者您有许多不同级别的运算符优先级时,这很有用。在您的情况下,您可以在几行中编写expression
...
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
-- ...
然后,在GHCi:
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)