Parsing a Formal Logic in Haskell
I have the following language I am trying to parse.
formula ::= true
| false
| var
| formula & formula
| ∀ var . formula
| (formula)
var ::= letter { letter | digit }*
I have been following this article on the Haskell wiki and have used Parsec combinators to create the following parser.
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)
The problem is the &
operator, I am trying to model it on how the article parses expressions, using the Infix
function and passing it a list of operators and a parser to parse terms. However, the parser is not behaving as desired and I can't work out why. Here are some examples of desired behaviour:
true -- parsing --> TT
true & false -- parsing --> Con TT FF
true & (true & false) -- parsing --> Con TT (Con TT FF)
forall x . false & true -- parsing --> Con (Forall "x" FF) TT
However currently the parser is producing no output. I appreciate any assistance.
parsing haskell parsec
add a comment |
I have the following language I am trying to parse.
formula ::= true
| false
| var
| formula & formula
| ∀ var . formula
| (formula)
var ::= letter { letter | digit }*
I have been following this article on the Haskell wiki and have used Parsec combinators to create the following parser.
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)
The problem is the &
operator, I am trying to model it on how the article parses expressions, using the Infix
function and passing it a list of operators and a parser to parse terms. However, the parser is not behaving as desired and I can't work out why. Here are some examples of desired behaviour:
true -- parsing --> TT
true & false -- parsing --> Con TT FF
true & (true & false) -- parsing --> Con TT (Con TT FF)
forall x . false & true -- parsing --> Con (Forall "x" FF) TT
However currently the parser is producing no output. I appreciate any assistance.
parsing haskell parsec
@mschmidt Thanks, I'll fix that.
– Luke Collins
Nov 20 '18 at 13:03
When I try to parse, I get no output at all (I think it hangs/goes into an infinite loop). But if I removeconformula
from the parserformula
(i.e. if I doformula = formulaTerm <|> varFormula <|> forallFormula
), the parser works as desired.
– Luke Collins
Nov 20 '18 at 13:16
Ok, I don't think, I know it goes into an infinite loop (it slowed down my computer after a while). Here's the output.
– Luke Collins
Nov 20 '18 at 13:26
add a comment |
I have the following language I am trying to parse.
formula ::= true
| false
| var
| formula & formula
| ∀ var . formula
| (formula)
var ::= letter { letter | digit }*
I have been following this article on the Haskell wiki and have used Parsec combinators to create the following parser.
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)
The problem is the &
operator, I am trying to model it on how the article parses expressions, using the Infix
function and passing it a list of operators and a parser to parse terms. However, the parser is not behaving as desired and I can't work out why. Here are some examples of desired behaviour:
true -- parsing --> TT
true & false -- parsing --> Con TT FF
true & (true & false) -- parsing --> Con TT (Con TT FF)
forall x . false & true -- parsing --> Con (Forall "x" FF) TT
However currently the parser is producing no output. I appreciate any assistance.
parsing haskell parsec
I have the following language I am trying to parse.
formula ::= true
| false
| var
| formula & formula
| ∀ var . formula
| (formula)
var ::= letter { letter | digit }*
I have been following this article on the Haskell wiki and have used Parsec combinators to create the following parser.
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)
The problem is the &
operator, I am trying to model it on how the article parses expressions, using the Infix
function and passing it a list of operators and a parser to parse terms. However, the parser is not behaving as desired and I can't work out why. Here are some examples of desired behaviour:
true -- parsing --> TT
true & false -- parsing --> Con TT FF
true & (true & false) -- parsing --> Con TT (Con TT FF)
forall x . false & true -- parsing --> Con (Forall "x" FF) TT
However currently the parser is producing no output. I appreciate any assistance.
parsing haskell parsec
parsing haskell parsec
edited Nov 20 '18 at 13:01
Luke Collins
asked Nov 20 '18 at 12:41
Luke CollinsLuke Collins
622622
622622
@mschmidt Thanks, I'll fix that.
– Luke Collins
Nov 20 '18 at 13:03
When I try to parse, I get no output at all (I think it hangs/goes into an infinite loop). But if I removeconformula
from the parserformula
(i.e. if I doformula = formulaTerm <|> varFormula <|> forallFormula
), the parser works as desired.
– Luke Collins
Nov 20 '18 at 13:16
Ok, I don't think, I know it goes into an infinite loop (it slowed down my computer after a while). Here's the output.
– Luke Collins
Nov 20 '18 at 13:26
add a comment |
@mschmidt Thanks, I'll fix that.
– Luke Collins
Nov 20 '18 at 13:03
When I try to parse, I get no output at all (I think it hangs/goes into an infinite loop). But if I removeconformula
from the parserformula
(i.e. if I doformula = formulaTerm <|> varFormula <|> forallFormula
), the parser works as desired.
– Luke Collins
Nov 20 '18 at 13:16
Ok, I don't think, I know it goes into an infinite loop (it slowed down my computer after a while). Here's the output.
– Luke Collins
Nov 20 '18 at 13:26
@mschmidt Thanks, I'll fix that.
– Luke Collins
Nov 20 '18 at 13:03
@mschmidt Thanks, I'll fix that.
– Luke Collins
Nov 20 '18 at 13:03
When I try to parse, I get no output at all (I think it hangs/goes into an infinite loop). But if I remove
conformula
from the parser formula
(i.e. if I do formula = formulaTerm <|> varFormula <|> forallFormula
), the parser works as desired.– Luke Collins
Nov 20 '18 at 13:16
When I try to parse, I get no output at all (I think it hangs/goes into an infinite loop). But if I remove
conformula
from the parser formula
(i.e. if I do formula = formulaTerm <|> varFormula <|> forallFormula
), the parser works as desired.– Luke Collins
Nov 20 '18 at 13:16
Ok, I don't think, I know it goes into an infinite loop (it slowed down my computer after a while). Here's the output.
– Luke Collins
Nov 20 '18 at 13:26
Ok, I don't think, I know it goes into an infinite loop (it slowed down my computer after a while). Here's the output.
– Luke Collins
Nov 20 '18 at 13:26
add a comment |
2 Answers
2
active
oldest
votes
I think I managed to fix the problem by rephrasing the grammar, and conjunction is still left-associative:
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
This parsed the following successfully.
Looks OK for me, since it successfully parsed thett & ff & tt
. I never tried to usebuildExpressionParser
, but the trick is to parse for terms within the conjunction, not for formulas.
– mschmidt
Nov 20 '18 at 23:07
SinceconFormula
can already match a singleformulaTern
, you don't needformulaTerm
as an alternative interm
.
– sepp2k
Nov 20 '18 at 23:50
add a comment |
The problem in your code is, that you try to parse a formula
for which the first attempt is to parse a formulaCon
. This then first tries to parse a formula
, i.e. you create an infinite recursion without consuming any input.
To resolve this, you have to structure your grammar. Define your terms like this (note that all these terms consume some input before doing a recursion back to formula
):
formulaTerm = ttFormula
<|> ffFormula
<|> varFormula
<|> forallFormula
<|> roundBrackets formula
forallFormula = do
keyword "forall"
x <- identifier
op "."
phi <- formula
return $ Forall x phi
A formula is then either a single term or a conjunction consisting of term, an operator, and another formula. To ensure that all input is parsed, first try to parse a conjunction and - if that fails - parse a single term:
formula = (try formulaCon) <|> formulaTerm
Finally a formulaCon
can be parsed like this:
formulaCon = do
f1 <- formulaTerm
op "&"
f2 <- formula
return $ Con f1 f2
The drawback with this solution is that conjunctions are now right associative.
I like this solution, although I'm not sure why we need atry
for theformulaCon
. I think I managed to fix it by rephrasing the grammar, preserving left-associativity. Could you take a look at it and check whether it's correct? I posted it as an answer.
– Luke Collins
Nov 20 '18 at 22:13
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53393220%2fparsing-a-formal-logic-in-haskell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I think I managed to fix the problem by rephrasing the grammar, and conjunction is still left-associative:
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
This parsed the following successfully.
Looks OK for me, since it successfully parsed thett & ff & tt
. I never tried to usebuildExpressionParser
, but the trick is to parse for terms within the conjunction, not for formulas.
– mschmidt
Nov 20 '18 at 23:07
SinceconFormula
can already match a singleformulaTern
, you don't needformulaTerm
as an alternative interm
.
– sepp2k
Nov 20 '18 at 23:50
add a comment |
I think I managed to fix the problem by rephrasing the grammar, and conjunction is still left-associative:
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
This parsed the following successfully.
Looks OK for me, since it successfully parsed thett & ff & tt
. I never tried to usebuildExpressionParser
, but the trick is to parse for terms within the conjunction, not for formulas.
– mschmidt
Nov 20 '18 at 23:07
SinceconFormula
can already match a singleformulaTern
, you don't needformulaTerm
as an alternative interm
.
– sepp2k
Nov 20 '18 at 23:50
add a comment |
I think I managed to fix the problem by rephrasing the grammar, and conjunction is still left-associative:
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
This parsed the following successfully.
I think I managed to fix the problem by rephrasing the grammar, and conjunction is still left-associative:
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
This parsed the following successfully.
answered Nov 20 '18 at 22:11
Luke CollinsLuke Collins
622622
622622
Looks OK for me, since it successfully parsed thett & ff & tt
. I never tried to usebuildExpressionParser
, but the trick is to parse for terms within the conjunction, not for formulas.
– mschmidt
Nov 20 '18 at 23:07
SinceconFormula
can already match a singleformulaTern
, you don't needformulaTerm
as an alternative interm
.
– sepp2k
Nov 20 '18 at 23:50
add a comment |
Looks OK for me, since it successfully parsed thett & ff & tt
. I never tried to usebuildExpressionParser
, but the trick is to parse for terms within the conjunction, not for formulas.
– mschmidt
Nov 20 '18 at 23:07
SinceconFormula
can already match a singleformulaTern
, you don't needformulaTerm
as an alternative interm
.
– sepp2k
Nov 20 '18 at 23:50
Looks OK for me, since it successfully parsed the
tt & ff & tt
. I never tried to use buildExpressionParser
, but the trick is to parse for terms within the conjunction, not for formulas.– mschmidt
Nov 20 '18 at 23:07
Looks OK for me, since it successfully parsed the
tt & ff & tt
. I never tried to use buildExpressionParser
, but the trick is to parse for terms within the conjunction, not for formulas.– mschmidt
Nov 20 '18 at 23:07
Since
conFormula
can already match a single formulaTern
, you don't need formulaTerm
as an alternative in term
.– sepp2k
Nov 20 '18 at 23:50
Since
conFormula
can already match a single formulaTern
, you don't need formulaTerm
as an alternative in term
.– sepp2k
Nov 20 '18 at 23:50
add a comment |
The problem in your code is, that you try to parse a formula
for which the first attempt is to parse a formulaCon
. This then first tries to parse a formula
, i.e. you create an infinite recursion without consuming any input.
To resolve this, you have to structure your grammar. Define your terms like this (note that all these terms consume some input before doing a recursion back to formula
):
formulaTerm = ttFormula
<|> ffFormula
<|> varFormula
<|> forallFormula
<|> roundBrackets formula
forallFormula = do
keyword "forall"
x <- identifier
op "."
phi <- formula
return $ Forall x phi
A formula is then either a single term or a conjunction consisting of term, an operator, and another formula. To ensure that all input is parsed, first try to parse a conjunction and - if that fails - parse a single term:
formula = (try formulaCon) <|> formulaTerm
Finally a formulaCon
can be parsed like this:
formulaCon = do
f1 <- formulaTerm
op "&"
f2 <- formula
return $ Con f1 f2
The drawback with this solution is that conjunctions are now right associative.
I like this solution, although I'm not sure why we need atry
for theformulaCon
. I think I managed to fix it by rephrasing the grammar, preserving left-associativity. Could you take a look at it and check whether it's correct? I posted it as an answer.
– Luke Collins
Nov 20 '18 at 22:13
add a comment |
The problem in your code is, that you try to parse a formula
for which the first attempt is to parse a formulaCon
. This then first tries to parse a formula
, i.e. you create an infinite recursion without consuming any input.
To resolve this, you have to structure your grammar. Define your terms like this (note that all these terms consume some input before doing a recursion back to formula
):
formulaTerm = ttFormula
<|> ffFormula
<|> varFormula
<|> forallFormula
<|> roundBrackets formula
forallFormula = do
keyword "forall"
x <- identifier
op "."
phi <- formula
return $ Forall x phi
A formula is then either a single term or a conjunction consisting of term, an operator, and another formula. To ensure that all input is parsed, first try to parse a conjunction and - if that fails - parse a single term:
formula = (try formulaCon) <|> formulaTerm
Finally a formulaCon
can be parsed like this:
formulaCon = do
f1 <- formulaTerm
op "&"
f2 <- formula
return $ Con f1 f2
The drawback with this solution is that conjunctions are now right associative.
I like this solution, although I'm not sure why we need atry
for theformulaCon
. I think I managed to fix it by rephrasing the grammar, preserving left-associativity. Could you take a look at it and check whether it's correct? I posted it as an answer.
– Luke Collins
Nov 20 '18 at 22:13
add a comment |
The problem in your code is, that you try to parse a formula
for which the first attempt is to parse a formulaCon
. This then first tries to parse a formula
, i.e. you create an infinite recursion without consuming any input.
To resolve this, you have to structure your grammar. Define your terms like this (note that all these terms consume some input before doing a recursion back to formula
):
formulaTerm = ttFormula
<|> ffFormula
<|> varFormula
<|> forallFormula
<|> roundBrackets formula
forallFormula = do
keyword "forall"
x <- identifier
op "."
phi <- formula
return $ Forall x phi
A formula is then either a single term or a conjunction consisting of term, an operator, and another formula. To ensure that all input is parsed, first try to parse a conjunction and - if that fails - parse a single term:
formula = (try formulaCon) <|> formulaTerm
Finally a formulaCon
can be parsed like this:
formulaCon = do
f1 <- formulaTerm
op "&"
f2 <- formula
return $ Con f1 f2
The drawback with this solution is that conjunctions are now right associative.
The problem in your code is, that you try to parse a formula
for which the first attempt is to parse a formulaCon
. This then first tries to parse a formula
, i.e. you create an infinite recursion without consuming any input.
To resolve this, you have to structure your grammar. Define your terms like this (note that all these terms consume some input before doing a recursion back to formula
):
formulaTerm = ttFormula
<|> ffFormula
<|> varFormula
<|> forallFormula
<|> roundBrackets formula
forallFormula = do
keyword "forall"
x <- identifier
op "."
phi <- formula
return $ Forall x phi
A formula is then either a single term or a conjunction consisting of term, an operator, and another formula. To ensure that all input is parsed, first try to parse a conjunction and - if that fails - parse a single term:
formula = (try formulaCon) <|> formulaTerm
Finally a formulaCon
can be parsed like this:
formulaCon = do
f1 <- formulaTerm
op "&"
f2 <- formula
return $ Con f1 f2
The drawback with this solution is that conjunctions are now right associative.
answered Nov 20 '18 at 21:53
mschmidtmschmidt
1,96941019
1,96941019
I like this solution, although I'm not sure why we need atry
for theformulaCon
. I think I managed to fix it by rephrasing the grammar, preserving left-associativity. Could you take a look at it and check whether it's correct? I posted it as an answer.
– Luke Collins
Nov 20 '18 at 22:13
add a comment |
I like this solution, although I'm not sure why we need atry
for theformulaCon
. I think I managed to fix it by rephrasing the grammar, preserving left-associativity. Could you take a look at it and check whether it's correct? I posted it as an answer.
– Luke Collins
Nov 20 '18 at 22:13
I like this solution, although I'm not sure why we need a
try
for the formulaCon
. I think I managed to fix it by rephrasing the grammar, preserving left-associativity. Could you take a look at it and check whether it's correct? I posted it as an answer.– Luke Collins
Nov 20 '18 at 22:13
I like this solution, although I'm not sure why we need a
try
for the formulaCon
. I think I managed to fix it by rephrasing the grammar, preserving left-associativity. Could you take a look at it and check whether it's correct? I posted it as an answer.– Luke Collins
Nov 20 '18 at 22:13
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53393220%2fparsing-a-formal-logic-in-haskell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
@mschmidt Thanks, I'll fix that.
– Luke Collins
Nov 20 '18 at 13:03
When I try to parse, I get no output at all (I think it hangs/goes into an infinite loop). But if I remove
conformula
from the parserformula
(i.e. if I doformula = formulaTerm <|> varFormula <|> forallFormula
), the parser works as desired.– Luke Collins
Nov 20 '18 at 13:16
Ok, I don't think, I know it goes into an infinite loop (it slowed down my computer after a while). Here's the output.
– Luke Collins
Nov 20 '18 at 13:26