03-编译小Parser
作者:互联网
可以使用很多工具编译之,因为我们的运行时库是VS构建的,为了不出问题也为了操作简单,仍旧使用VS建立项目。
建立工程
创建一个TestL的Cpp空项目,并将Cpp文件复制到工程文件中去。注意只要cpp和h文件就可以,其他的辅助文件不需要。然后将所有的文件添加到工程中。
新建一个main.cpp文件,写一个做简单的helloworld程序,如下:
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Hello World" << std::endl;
return 0;
}
配置项目,把运行时库添加进来。如下:
然后编译测试一下。正常情况下会出现大量C4251警告,但这是Antlr运行时的问题,忽略就好了。如果没有报错,说明配置正确,可以进行下一步的工作了。
Visitor模式与Listener模式
这两种模式有本质的区别,但其实都能完成工作,个人喜欢visitor模式。具体请参看官方文档。
TestLVisitor类是接口类,TestLBaseVisitor是其默认实现,但我们往往需要修改一些默认实现,所以这里新建一个MyTestLVisitor类,继承自TestLBaseVisitor类,并重新实现接口方法。
visitDoc没必要重新实现,visitItem重新实现,我们希望当解析出一个item的时候输出到屏幕上。
在MyTestLVisitor.h中,代码如下:
#pragma once
#include "antlr4-runtime.h"
#include "TestLBaseVisitor.h"
#include <iostream>
class MyTestLVisitor :
public TestLBaseVisitor
{
virtual antlrcpp::Any visitItem(TestLParser::ItemContext* ctx) override {
std::cout << "Name:" << ctx->STRING()->getText()
<< "Age:" << ctx->NUM().at(0)->getText()
<< "Height" << ctx->NUM().at(1)->getText()
<< std::endl;
return defaultResult();
}
};
ctx,就是识别出来的那个结构,这里是item。每一个item只包含一个STRING数据,所以STRING()方法返回一个对象,如果是多个,则返回一个vector。
解析过程
在main.cpp里面修改代码如下:
#include "antlr4-runtime.h"
#include "TestLLexer.h"
#include "TestLParser.h"
#include "MyTestLVisitor.h"
int main(int argc, char** argv) {
// 建立一个字符流,可以从input,可以从文件。
antlr4::ANTLRFileStream* file = new antlr4::ANTLRFileStream();
file->loadFromFile("test.txt");
// 词法分析,生成token流
TestLLexer* lexer = new TestLLexer(file);
antlr4::CommonTokenStream* tokenstream = new antlr4::CommonTokenStream(lexer);
// 语法分析,并使用visitor处理ast。
TestLParser* parser = new TestLParser(tokenstream);
MyTestLVisitor* visitor = new MyTestLVisitor();
visitor->visit(parser->doc());
// 释放内存
delete visitor;
delete parser;
delete tokenstream;
delete lexer;
delete file;
return 0;
}
编译。生成一个TestL.exe,把antlr4-runtime.dll复制过来(或者设置调试环境也行,随便了),在同目录下建立一个test.txt文件(源码中写死了),并在其中写入以下内容:
Name{小强}Age{11}Height{23}
Name{小强}Age{11}Height{23}
注意txt文件的编码格式如果是ANSI,直接运行,如果是UTF8,需要用chcp 65001切换代码页,不然是乱码。得到如下结果:
可以看到,我们自定义的visitor成功的解析了文本数据,并执行了我们自定义的动作。
小结
本文和前面一篇,就是使用antlr进行结构化文本数据处理的简单完整的流程,当然有很多地方并没有覆盖到,比如复杂规则的定义(岛语言,左递归等),比如解析过程中的错误处理等等。有时间再写那些东西吧,比较蛋疼。
标签:03,visitor,Parser,MyTestLVisitor,编译,antlr4,new,include,delete 来源: https://blog.csdn.net/xuanjueheshang/article/details/115875307