Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing Haskell中形式逻辑的解析_Parsing_Haskell_Parsec - Fatal编程技术网

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