其他分享
首页 > 其他分享> > 03-编译小Parser

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;
}

配置项目,把运行时库添加进来。如下:
includelib目录lib文件
然后编译测试一下。正常情况下会出现大量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