如何使用 Parsec 解析三元表达式?
How to parse ternary expression using Parsec?
buildExpressionParser only deals with unary and binary operators. Can it handle ternary operators like ?:
? There are some discussions here and here,但none是决定性的。
monadic 解析器的一大好处是它们的组合非常好。
这意味着您不必试图欺骗单个 buildExpressionParser
来构建您想要的确切解析器。您可以简单地使用它来构建一个解析器,然后像使用任何其他解析器一样使用该解析器来处理任何事情,包括另一个 buildExpressionParser
.
对于您的情况,您可以:
- 使用
buildExpressionParser
为优先级高于 ?:
的表达式创建解析器
- 使用上述
为?:
创建解析器
- 使用
buildExpressionParser
为优先级低于 ?:
的表达式创建解析器,使用上述
这是一个完整的例子:
import Control.Monad.Identity
import Text.Parsec
import Text.Parsec.Expr
data Ex = Var String | Mul Ex Ex | Add Ex Ex | Assign Ex Ex | Trinary Ex Ex Ex
deriving (Show)
var = Var <$> many1 letter
topOps = [ [binary "*" Mul], [binary "+" Add] ]
topParser = buildExpressionParser topOps var
trinaryExpr = do
expr <- topParser
trinary expr <|> return expr
where
trinary expr = do
string "?"
thenV <- trinaryExpr
string ":"
elseV <- trinaryExpr
return $ Trinary expr thenV elseV
bottomOps = [ [ binary "=" Assign ] ]
bottomParser = buildExpressionParser bottomOps trinaryExpr
binary :: String -> (Ex -> Ex -> Ex) -> Operator String () Identity Ex
binary s t = Infix (string s >> return t) AssocLeft
testParse s = runParser bottomParser () "" s
main = print $ testParse "a=b+c*d?e+f:g*h"
输出(手动格式化)为:
Right
(Assign
(Var "a")
(Trinary
(Add (Var "b")
(Mul (Var "c") (Var "d")))
(Add (Var "e") (Var "f"))
(Mul (Var "g") (Var "h"))))
buildExpressionParser only deals with unary and binary operators. Can it handle ternary operators like ?:
? There are some discussions here and here,但none是决定性的。
monadic 解析器的一大好处是它们的组合非常好。
这意味着您不必试图欺骗单个 buildExpressionParser
来构建您想要的确切解析器。您可以简单地使用它来构建一个解析器,然后像使用任何其他解析器一样使用该解析器来处理任何事情,包括另一个 buildExpressionParser
.
对于您的情况,您可以:
- 使用
buildExpressionParser
为优先级高于?:
的表达式创建解析器
- 使用上述 为
- 使用
buildExpressionParser
为优先级低于?:
的表达式创建解析器,使用上述
?:
创建解析器
这是一个完整的例子:
import Control.Monad.Identity
import Text.Parsec
import Text.Parsec.Expr
data Ex = Var String | Mul Ex Ex | Add Ex Ex | Assign Ex Ex | Trinary Ex Ex Ex
deriving (Show)
var = Var <$> many1 letter
topOps = [ [binary "*" Mul], [binary "+" Add] ]
topParser = buildExpressionParser topOps var
trinaryExpr = do
expr <- topParser
trinary expr <|> return expr
where
trinary expr = do
string "?"
thenV <- trinaryExpr
string ":"
elseV <- trinaryExpr
return $ Trinary expr thenV elseV
bottomOps = [ [ binary "=" Assign ] ]
bottomParser = buildExpressionParser bottomOps trinaryExpr
binary :: String -> (Ex -> Ex -> Ex) -> Operator String () Identity Ex
binary s t = Infix (string s >> return t) AssocLeft
testParse s = runParser bottomParser () "" s
main = print $ testParse "a=b+c*d?e+f:g*h"
输出(手动格式化)为:
Right
(Assign
(Var "a")
(Trinary
(Add (Var "b")
(Mul (Var "c") (Var "d")))
(Add (Var "e") (Var "f"))
(Mul (Var "g") (Var "h"))))