I would like to parse arithmetic expressions.
Here is my current parser:
data AExpr
= ExprAsAExpr Expr
| IntConst Integer
| Neg AExpr
| ABinary ABinOp AExpr AExpr
deriving (Show, Eq)
aExpr :: Parser AExpr
aExpr = makeExprParser aTerm aOperators
aTerm :: Parser AExpr
aTerm
= parens aExpr
<|> IntConst <$> integerParser
aOperators :: [[Operator Parser AExpr]]
aOperators =
[ [Prefix (Neg <$ symbol "-") ]
, [ InfixL (ABinary Multiply <$ symbol "*")
, InfixL (ABinary Divide <$ symbol "/") ]
, [ InfixL (ABinary Add <$ symbol "+")
, InfixL (ABinary Subtract <$ symbol "-") ]
]
Using this I can correctly parse this:
1 + 2
Generating an AST like this.
(ABinary Add (IntConst 1) (IntConst 2))
Another thing I can parse are general expressions. These can be things such as variables, method calls, ternaries etc.
E.g.
Identifiers:
varName
This generates:
(Identifier (Name "varName"))
Method Calls:
methodCall()
This generates:
(MethodCall (Name "methodCall") (BlockExpr []))
Here's an example for parsing general expressions.
expressionParser :: Parser Expr
expressionParser
= methodCallParser
<|> identifierParser
This works fine but I would also like to parse arithmetic expressions in this.
expressionParser :: Parser Expr
expressionParser
= newClassInstanceParser
<|> methodCallParser
<|> AExprAsExpr <$> aExpr
<|> identifierParser
This means using the expressionParser I can now parse all the different expressions including arithmetic expressions. If it happens to be an arithmetic expression it gets wrapped in AExprAsExpr.
Problem
I would like to parse arithmetic expressions containing other expressions.
E.g.
x + y
To do this my original thought was to change the arithmetic parser so it also parses expressions.
data AExpr
= ExprAsAExpr Expr
| IntConst Integer
| Neg AExpr
| ABinary ABinOp AExpr AExpr
deriving (Show, Eq)
aExpr :: Parser AExpr
aExpr = makeExprParser aTerm aOperators
aTerm :: Parser AExpr
aTerm
= parens aExpr
<|> IntConst <$> integerParser
<|> ExprAsAExpr <$> expressionParser
aOperators :: [[Operator Parser AExpr]]
aOperators =
[ [Prefix (Neg <$ symbol "-") ]
, [ InfixL (ABinary Multiply <$ symbol "*")
, InfixL (ABinary Divide <$ symbol "/") ]
, [ InfixL (ABinary Add <$ symbol "+")
, InfixL (ABinary Subtract <$ symbol "-") ]
]
The problem with this is there is a recursive loop as aTerm calls the expression parser, the expression parser calls aExpr. This leads to an infinite loop. There is also the issue that all identifiers will now be wrapped inside an AExprAsExpr.
What is the correct method of parsing expressions inside arithmetic expressions?
aExprandexpressionParser. - sepp2k