antlr4 C++入门 - antlr4 访问器和监听器计算结果
·
antlr4 C++入门 - antlr4 访问器和监听器计算结果
环境:
antlr4: 4.13.2 (2024-08-04)
java: jdk 11.0.27 LTS (2025-04-15, EOL:2032-01)
编译器:vs2022/g++ 12
前言
上节中介绍了在C++中输出算数表达式的解析树,本文将使用访问器和监听器两种方式计算结果。
1. 访问器模式visitor计算结果
#include <iostream>
#include "antlr4-runtime.h"
#include "calculatorLexer.h"
#include "calculatorParser.h"
#include "calculatorBaseVisitor.h" // visitor
using namespace itas109;
using namespace antlr4;
class myCalculatorVisitor : public calculatorBaseVisitor
{
virtual std::any visitProgram(calculatorParser::ProgramContext *ctx) override
{
return visit(ctx->expr());
}
virtual std::any visitMulDivExpr(calculatorParser::MulDivExprContext *ctx) override
{
int left = std::any_cast<int>(visit(ctx->expr(0)));
int right = std::any_cast<int>(visit(ctx->expr(1)));
if (ctx->Mul())
{
return left * right;
}
else if (ctx->Div())
{
return left / right;
}
return 0;
}
virtual std::any visitParensExpr(calculatorParser::ParensExprContext *ctx) override
{
return visit(ctx->expr());
}
virtual std::any visitAddSubExpr(calculatorParser::AddSubExprContext *ctx) override
{
int left = std::any_cast<int>(visit(ctx->expr(0)));
int right = std::any_cast<int>(visit(ctx->expr(1)));
if (ctx->Add())
{
return left + right;
}
else if (ctx->Sub())
{
return left - right;
}
return 0;
}
virtual std::any visitIntegerLiteral(calculatorParser::IntegerLiteralContext *ctx) override
{
return std::atoi(ctx->getText().c_str());
}
};
int main(int argc, const char *argv[])
{
const char *sourceCode = "1+2*3";
ANTLRInputStream input(sourceCode);
calculatorLexer lexer(&input);
CommonTokenStream tokens(&lexer);
calculatorParser parser(&tokens);
tree::ParseTree *tree = parser.program();
std::string stringTree = tree->toStringTree(&parser);
printf("Input: %s\nParse Tree: %s\n", sourceCode, stringTree.c_str());
myCalculatorVisitor visitor;
int result = std::any_cast<int>(visitor.visit(tree));
printf("result(visitor): %d\n", result);
printf("\nPress Enter To Continue\n");
(void)getchar();
return 0;
}
结果
Input: 1+2*3
Parse Tree: (program (expr (expr 1) + (expr (expr 2) * (expr 3))) <EOF>)
result(visitor): 7
2. 监听器模式listener计算结果
这里使用ParseTreeProperty类标记语法树,也可以使用栈临时存储(但不推荐)。
main.cpp
#include <iostream>
#include "antlr4-runtime.h"
#include "calculatorLexer.h"
#include "calculatorParser.h"
#include "ParseTreeProperty.h" // annotate
#include "calculatorBaseListener.h" // listener
using namespace itas109;
using namespace antlr4;
class myCalculatorListener : public calculatorBaseListener
{
public:
// annotate parse tree
tree::ParseTreeProperty<int> result;
void setValues(tree::ParseTree *node, int value)
{
result.put(node, value);
}
int getValues(tree::ParseTree *node)
{
return result.get(node);
}
virtual void exitProgram(calculatorParser::ProgramContext *ctx) override
{
setValues(ctx, getValues(ctx->expr()));
}
virtual void exitMulDivExpr(calculatorParser::MulDivExprContext *ctx) override
{
int left = getValues(ctx->expr(0));
int right = getValues(ctx->expr(1));
if (ctx->Mul())
{
setValues(ctx, left * right);
}
else if (ctx->Div())
{
setValues(ctx, left / right);
}
}
virtual void exitParensExpr(calculatorParser::ParensExprContext *ctx) override
{
setValues(ctx, getValues(ctx->expr()));
}
virtual void exitAddSubExpr(calculatorParser::AddSubExprContext *ctx) override
{
int left = getValues(ctx->expr(0));
int right = getValues(ctx->expr(1));
if (ctx->Add())
{
setValues(ctx, left + right);
}
else if (ctx->Sub())
{
setValues(ctx, left - right);
}
}
virtual void exitIntegerLiteral(calculatorParser::IntegerLiteralContext *ctx) override
{
setValues(ctx, std::atoi(ctx->getText().c_str()));
}
};
int main(int argc, const char *argv[])
{
const char *sourceCode = "1+2*3";
ANTLRInputStream input(sourceCode);
calculatorLexer lexer(&input);
CommonTokenStream tokens(&lexer);
calculatorParser parser(&tokens);
tree::ParseTree *tree = parser.program();
std::string stringTree = tree->toStringTree(&parser);
printf("Input: %s\nParse Tree: %s\n", sourceCode, stringTree.c_str());
myCalculatorListener listener;
antlr4::tree::ParseTreeWalker::DEFAULT.walk(&listener, tree);
printf("result(listener): %d\n", listener.getValues(tree));
printf("\nPress Enter To Continue\n");
(void)getchar();
return 0;
}
结果
Input: 1+2*3
Parse Tree: (program (expr (expr 1) + (expr (expr 2) * (expr 3))) <EOF>)
result(listener): 7
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)