Parsing Haskell中形式逻辑的解析
我正在尝试解析以下语言Parsing Haskell中形式逻辑的解析,parsing,haskell,parsec,Parsing,Haskell,Parsec,我正在尝试解析以下语言 formula ::= true | false | var | formula & formula | ∀ var . formula | (formula) var ::= letter { letter | digit }* 我一直关注Haskell wiki,并使用Parsec combinators创建了以下解析器 modu
formula ::= true
| false
| var
| formula & formula
| ∀ var . formula
| (formula)
var ::= letter { letter | digit }*
我一直关注Haskell wiki,并使用Parsec combinators创建了以下解析器
module LogicParser where
import System.IO
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
-- Data Structures
data Formula = Var String
| TT
| FF
| Con Formula Formula
| Forall String Formula
deriving (Show)
-- Language Definition
lang :: LanguageDef st
lang =
emptyDef{ Token.identStart = letter
, Token.identLetter = alphaNum
, Token.opStart = oneOf "&."
, Token.opLetter = oneOf "&."
, Token.reservedOpNames = ["&", "."]
, Token.reservedNames = ["tt", "ff", "forall"]
}
-- Lexer for langauge
lexer =
Token.makeTokenParser lang
-- Trivial Parsers
identifier = Token.identifier lexer
keyword = Token.reserved lexer
op = Token.reservedOp lexer
roundBrackets = Token.parens lexer
whiteSpace = Token.whiteSpace lexer
-- Main Parser, takes care of trailing whitespaces
formulaParser :: Parser Formula
formulaParser = whiteSpace >> formula
-- Parsing Formulas
formula :: Parser Formula
formula = conFormula
<|> formulaTerm
<|> forallFormula
-- Term in a Formula
formulaTerm :: Parser Formula
formulaTerm = roundBrackets formula
<|> ttFormula
<|> ffFormula
<|> varFormula
-- Conjunction
conFormula :: Parser Formula
conFormula =
buildExpressionParser [[Infix (op "&" >> return Con) AssocLeft]] formula
-- Truth
ttFormula :: Parser Formula
ttFormula = keyword "tt" >> return TT
-- Falsehood
ffFormula :: Parser Formula
ffFormula = keyword "ff" >> return FF
-- Variable
varFormula :: Parser Formula
varFormula =
do var <- identifier
return $ Var var
-- Universal Statement
forallFormula :: Parser Formula
forallFormula =
do keyword "forall"
x <- identifier
op "."
phi <- formulaTerm
return $ Forall x phi
-- For running runghc
calculate :: String -> String
calculate s =
case ret of
Left e -> "Error: " ++ (show e)
Right n -> "Interpreted as: " ++ (show n)
where
ret = parse formulaParser "" s
main :: IO ()
main = interact (unlines . (map calculate) . lines)
但是,当前解析器没有生成任何输出。非常感谢您的帮助。代码中的问题是,您试图解析一个
公式
,第一次尝试就是解析公式。然后首先尝试解析公式
,即创建无限递归,而不使用任何输入
要解决这个问题,你必须组织你的语法。像这样定义术语(请注意,所有这些术语在执行返回到公式的递归之前都会消耗一些输入):
这个解决方案的缺点是连接词现在是右关联的。我想我通过重新表述语法解决了这个问题,连接词仍然是左关联的:
formula :: Parser Formula
formula = conFormula
<|> formulaTerm
formulaTerm :: Parser Formula
formulaTerm = roundBrackets formula
<|> ttFormula
<|> ffFormula
<|> varFormula
<|> forallFormula
conFormula :: Parser Formula
conFormula =
buildExpressionParser [[Infix (op "&" >> return Con) AssocLeft]] formulaTerm
formula::解析器公式
公式=conFormula
公式术语
formulaTerm::解析器公式
formulaTerm=圆括号公式
TTF公式
FFR公式
变量公式
福尔公式
conFormula::解析器公式
一致性=
buildExpressionParser[[Infix(op“&”>>return Con)AssocLeft]]公式术语
这成功地解析了以下内容。
@mschmidt谢谢,我会解决这个问题。当我尝试解析时,我根本没有得到任何输出(我认为它挂起/进入无限循环)。但是如果我从解析器formula
中删除conformula
(也就是说,如果我删除formula=formulaTerm varFormula forallFormula
),解析器就会按预期工作。好吧,我不认为,我知道它会进入无限循环(它会在一段时间后减慢我的计算机)。下面是答案。我喜欢这个解决方案,尽管我不确定为什么我们需要试试formulaCon
。我想我通过重新表述语法,保留左联想性,成功地解决了这个问题。你能看一下它并检查它是否正确吗?我把它作为一个答案贴了出来。看起来还可以,因为它成功地解析了tt&ff&tt
。我从未尝试过使用buildExpressionParser
,但诀窍是在连接中解析术语,而不是解析公式。由于conFormula
已经可以匹配单个formulaTern
,您不需要在term
中使用formulaTerm
。
formulaTerm = ttFormula
<|> ffFormula
<|> varFormula
<|> forallFormula
<|> roundBrackets formula
forallFormula = do
keyword "forall"
x <- identifier
op "."
phi <- formula
return $ Forall x phi
formula = (try formulaCon) <|> formulaTerm
formulaCon = do
f1 <- formulaTerm
op "&"
f2 <- formula
return $ Con f1 f2
formula :: Parser Formula
formula = conFormula
<|> formulaTerm
formulaTerm :: Parser Formula
formulaTerm = roundBrackets formula
<|> ttFormula
<|> ffFormula
<|> varFormula
<|> forallFormula
conFormula :: Parser Formula
conFormula =
buildExpressionParser [[Infix (op "&" >> return Con) AssocLeft]] formulaTerm