Я бы хотел разобрать арифметические выражения.
Вот мой текущий парсер:
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 "-") ]
]
Используя это, я могу правильно разобрать это:
1 + 2
Генерация AST, как это.
(ABinary Add (IntConst 1) (IntConst 2))
Еще одна вещь, которую я могу разобрать, это общие выражения. Это могут быть такие вещи, как переменные, вызовы методов, троичные и т. Д.
* 1017 Е.Г. *
Идентификаторы:
varName
Создает:
(Identifier (Name "varName"))
Вызовы метода:
methodCall()
Создает:
(MethodCall (Name "methodCall") (BlockExpr []))
Вот пример для разбора общих выражений.
expressionParser :: Parser Expr
expressionParser
= methodCallParser
<|> identifierParser
Это работает нормально, но я бы также хотел разобрать арифметические выражения в этом.
expressionParser :: Parser Expr
expressionParser
= newClassInstanceParser
<|> methodCallParser
<|> AExprAsExpr <$> aExpr
<|> identifierParser
Это означает, что с помощью expressionParser
я могу теперь анализировать все различные выражения, включая арифметические выражения. Если это будет арифметическое выражение, оно будет заключено в AExprAsExpr
.
Проблема
Я хотел бы проанализировать арифметические выражения, содержащие другие выражения.
1052 * Е.Г. *
x + y
Для этого моей первоначальной мыслью было изменить арифметический синтаксический анализатор, чтобы он также анализировал выражения.
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 "-") ]
]
Проблема в том, что существует рекурсивный цикл, так как aTerm
вызывает синтаксический анализатор выражений, синтаксический анализатор выражений вызывает aExpr
. Это приводит к бесконечному циклу. Существует также проблема, заключающаяся в том, что все identifiers
теперь будут заключены в AExprAsExpr
.
Каков правильный метод анализа выражений внутри арифметических выражений?