将中缀运算符添加到表达式解析器
Adding infix operator to expression parser
我正在尝试将中缀运算符的解析器添加到简单的表达式解析器。我已经看过 documentation and at this question,但我好像漏掉了什么。
import qualified Text.Parsec.Expr as Expr
import qualified Text.Parsec.Token as Tokens
import Text.ParserCombinators.Parsec
import Text.Parsec
data Expr = Number Integer
| Op Expr Expr
| Boolean Bool
instance Show Expr where
show (Op l r) = "(+ " ++ (show l) ++ " " ++ (show r) ++ ")"
show (Number r) = show r
show (Boolean b) = show b
parens = Tokens.parens haskell
reserved = Tokens.reservedOp haskell
infix_ operator func =
Expr.Infix (spaces >> reserved operator >> spaces >> return func) Expr.AssocLeft
infixOp =
Expr.buildExpressionParser table parser
where
table = [[infix_ "+" Op]]
number :: Parser Expr
number =
do num <- many1 digit
return $ Number $ read num
bool :: Parser Expr
bool = (string "true" >> return (Boolean True)) <|> (string "false" >> return (Boolean False))
parser = parens infixOp <|> number <|> bool
run = Text.Parsec.runParser parser () ""
此解析器能够解析 1
、false
、(1 + 2)
、(1 + false)
等表达式,但不能解析 1 + 2
(它被解析为 1
).如果我尝试将解析器更改为 parens infixOp <|> infixOp <|> number <|> bool
,它会卡住。
我应该更改什么才能解析像 1 + 2
这样不带括号的表达式?
您必须像这样 运行 顶层的 infixOp
解析器:
run = Text.Parsec.runParser infixOp () ""
否则你的中缀表达式只能在出现在括号中时被解析。
尝试使用 parens infixOp <|> infixOp <|> number <|> bool
很可能会卡住,因为它会循环:parser
尝试使用 infixOp
进行解析,后者尝试使用 parse
进行解析,依此类推...
这些教程可能会帮助您开始使用 parsec(他们为我做了):
https://wiki.haskell.org/Parsing_a_simple_imperative_language
我正在尝试将中缀运算符的解析器添加到简单的表达式解析器。我已经看过 documentation and at this question,但我好像漏掉了什么。
import qualified Text.Parsec.Expr as Expr
import qualified Text.Parsec.Token as Tokens
import Text.ParserCombinators.Parsec
import Text.Parsec
data Expr = Number Integer
| Op Expr Expr
| Boolean Bool
instance Show Expr where
show (Op l r) = "(+ " ++ (show l) ++ " " ++ (show r) ++ ")"
show (Number r) = show r
show (Boolean b) = show b
parens = Tokens.parens haskell
reserved = Tokens.reservedOp haskell
infix_ operator func =
Expr.Infix (spaces >> reserved operator >> spaces >> return func) Expr.AssocLeft
infixOp =
Expr.buildExpressionParser table parser
where
table = [[infix_ "+" Op]]
number :: Parser Expr
number =
do num <- many1 digit
return $ Number $ read num
bool :: Parser Expr
bool = (string "true" >> return (Boolean True)) <|> (string "false" >> return (Boolean False))
parser = parens infixOp <|> number <|> bool
run = Text.Parsec.runParser parser () ""
此解析器能够解析 1
、false
、(1 + 2)
、(1 + false)
等表达式,但不能解析 1 + 2
(它被解析为 1
).如果我尝试将解析器更改为 parens infixOp <|> infixOp <|> number <|> bool
,它会卡住。
我应该更改什么才能解析像 1 + 2
这样不带括号的表达式?
您必须像这样 运行 顶层的 infixOp
解析器:
run = Text.Parsec.runParser infixOp () ""
否则你的中缀表达式只能在出现在括号中时被解析。
尝试使用 parens infixOp <|> infixOp <|> number <|> bool
很可能会卡住,因为它会循环:parser
尝试使用 infixOp
进行解析,后者尝试使用 parse
进行解析,依此类推...
这些教程可能会帮助您开始使用 parsec(他们为我做了):
https://wiki.haskell.org/Parsing_a_simple_imperative_language