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?