Antlr4安装与使用(包括python3与C++版本) 2018-12-21

3 篇文章 0 订阅

本文中包括:

  1. antlr4的安装;
  2. python3中使用antlr4的说明;
  3. C++中使用antlr的说明。

安装

JDK安装

直接在百度搜索【JDK安装】即可。Windows系统可以参考视频: https://www.bilibili.com/video/BV1uv411u7vF/

需要保证:安装完后,终端或命令行中输入javajavac都能找到对应的命令。

Antlr安装

参考官网主页。

Ubuntu安装

安装方法:(来自官网首页,Quick Start)

$ cd /usr/local/lib
$ wget https://www.antlr.org/download/antlr-4.7.2-complete.jar
$ export CLASSPATH=".:/usr/local/lib/antlr-4.7.2-complete.jar:$CLASSPATH"
$ alias antlr4='java -jar /usr/local/lib/antlr-4.7.2-complete.jar'
$ alias grun='java org.antlr.v4.gui.TestRig'

直接运行antlr4grun出现帮助信息就说明成功。

第二步下载的时候如果权限不够,就sudo下载并且之后sudo chmod 777 antlr-4.7.2-complete.jar

然后为方便使用,在.bashrc里面添加后三行:

export CLASSPATH=".:/usr/local/lib/antlr-4.7.2-complete.jar:$CLASSPATH"
alias antlr4='java -jar /usr/local/lib/antlr-4.7.2-complete.jar'
alias grun='java org.antlr.v4.gui.TestRig'

一定要注意这里的CLASSPATH里面要有.!也就是CLASSPATH定义时,".:/usr/local/lib/antlr-4.7.2-complete.jar:$CLASSPATH"引号里面,开头是有一个英文句号.和一个英文冒号:的!!!!!!!

Windows安装

可以参考视频:https://www.bilibili.com/video/BV1Nh411n7wW/

下载antlr的jar包(最新版为 https://www.antlr.org/download/antlr-4.9.2-complete.jar ),将下载的.jar文件的路径与.添加到CLASSPATH中。

要特别注意,.一定要添加到CLASSPATH中!!!!!!!如下图所示:

CLASSPATH示例

创建两个bat文件:

antlr4.bat

java org.antlr.v4.Tool %*

grun.bat

java org.antlr.v4.gui.TestRig %*

将这两个.bat文件的路径放在环境变量Path中,命令行中执行antlr4grun能正常显示即可。

使用

(官方GetStarted:https://github.com/antlr/antlr4/blob/master/doc/getting-started.md

g4部分

创建文件Hello.g4,如下:

grammar Hello;
r  : 'hello' ID ;         // match keyword hello followed by an identifier
ID : [a-z]+ ;             // match lower-case identifiers
WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines

执行antlr4 Hello.g4javac Hello*.java

之后grun Hello r -tree或者grun Hello r -gui,输入某一个输入串(如hello henryfox)后回车并按下Ctrl-D(Windows下为Ctrl-Z),就可以看到解析结果。

这里的r表示的是第二行的起始符号r

python部分

(官方说明:https://github.com/antlr/antlr4/blob/master/doc/python-target.md

准备python库:

pip install antlr4-python3-runtime

执行antlr4,其中需要声明Dlanguageantlr4 -Dlanguage=Python3 Hello.g4 (注意是Python3,P要大写!)

之后在那个执行antlr4的目录下,创建以下程序并运行:

import sys
from antlr4 import *
from HelloLexer import HelloLexer
from HelloParser import HelloParser
from HelloListener import HelloListener
 
class HelloPrintListener(HelloListener):
    def enterR(self, ctx):
        # 函数名enterR的R指的是非终结符r
        print("Hello: %s" % ctx.ID())


def main():
    lexer = HelloLexer(StdinStream())
    stream = CommonTokenStream(lexer)
    parser = HelloParser(stream)
    tree = parser.r()
    printer = HelloPrintListener()
    walker = ParseTreeWalker()
    walker.walk(printer, tree)
 
if __name__ == '__main__':
    main()

还是直接启动后输入hello henryfox并且回车,输入Ctrl-D(Windows环境输入Ctrl-Z

示例:Visitor实现四则运算的计算

文法规则文件Expr.g4

grammar Expr;		
prog:	expr NEWLINE            # printExpr;
expr:	left=expr op=('*'|'/') right=expr   # mulDiv    // 用来确定优先级,在上面的优先级高
    |	left=expr op=('+'|'-') right=expr   # addSub
    |	INT                     # int
    |	'(' expr ')'            # brackets
    ;
NEWLINE : [\r\n]+ ;
INT     : [0-9]+ ;

MUL     : '*' ;  // 用来便于当作常量引用
DIV     : '/' ;
ADD     : '+' ;
SUB     : '-' ;

在执行antlr4的时候需要指明-no-listener-visitor,因此执行antlr4 -no-listener -visitor -Dlanguage=Python3 Expr.g4

创建文件Expr.py

import sys
from antlr4 import *
from ExprLexer import ExprLexer
from ExprParser import ExprParser
from ExprVisitor import ExprVisitor
 
class ExprCalculateVisitor(ExprVisitor):
    def visitPrintExpr(self, ctx):
        # 函数名enterR的R指的是非终结符r
        val = self.visit(ctx.expr())
        print(val)
        return val

    def visitBrackets(self, ctx):
        return self.visit(ctx.expr())
    
    def visitAddSub(self, ctx):
        if ctx.op.type == ExprParser.ADD:
            return self.visit(ctx.left) + self.visit(ctx.right)
        else:
            return self.visit(ctx.left) - self.visit(ctx.right)

    def visitMulDiv(self, ctx):
        if ctx.op.type == ExprParser.MUL:
            return self.visit(ctx.left) * self.visit(ctx.right)
        else:
            return self.visit(ctx.left) / self.visit(ctx.right)

    def visitInt(self, ctx):
        return int(ctx.getText())


def main():
    lexer = ExprLexer(StdinStream())
    stream = CommonTokenStream(lexer)
    parser = ExprParser(stream)
    tree = parser.prog()
    calculator = ExprCalculateVisitor()
    calculator.visitPrintExpr(tree)
 
if __name__ == '__main__':
    main()

这里的visitXXX的XXX部分都是上面#后的内容;如果不写#后的东西,就会是visitProg之类的

之后仍然是运行并且输入后回车输入EOF(Ctrl-D/Ctrl-Z)即可看到结果输出

C++版本

官方demo

按照官网首页配置好,测试能够使用antlr4和grun命令之后:

创建自己的项目

如果要自己创建antlr4的项目,在刚才几步能正常执行之后,在【这个刚刚打开的解决方案里面】创建自己的项目:

新建项目

注意选择【添加到解决方案】。

修改以下属性:

  • 【新建的项目】里【引用】右键【添加引用】,选上antlr4cpp-vs2015
  • 添加引用
  • antlr4cpp-vs2015
  • 【源文件】-右键【添加】-【现有项】,选中上面几级目录的demo\generated文件夹下所有h、cpp文件
  • 添加generate文件
  • 新建一个main.cpp,里面复制过来antlr4cpp-demo的main.cpp
  • 在【新建的项目】上右键【属性】打开属性页面(这时,单击antlr4cpp-demo这个项目会切换到这个项目的对应属性,可以直接方便地复制粘贴),把antlr4cpp-demo的以下属性复制过来:
    • 复制【输出目录】
    • 输出目录
    • 修改【字符集】为Unicode
    • 字符集
    • 复制【C/C++】-【常规】-【附加包含目录】
    • 附加包含目录
  • 右上角【配置管理器】-找到这个项目后【编辑】,重命名为Debug DLL
  • 编辑
  • 重命名
  • 运行&改编码(选择是,因为之前把字符集改成了Unicode)
  • 改编码

之后就可以运行了!

ANTLR的lib生成

LIB介绍

LIB生成&使用:https://www.cnblogs.com/TenosDoIt/p/3203137.html

LIB创建

用桌面向导创建一个空的LIB

桌面向导

弹出的应用程序类型选择.lib

新建MyLIB.h

#pragma once
void fun(int a);

extern int k;

class testclass
{
public:
    testclass();
    void print();
};

MyLIB.cpp

#include "stdafx.h"
#include "MyLIB.h"
#include <iostream>

void fun(int a)
{
    std::cout << a << "lib gen\n";
}

int k = 222;

testclass::testclass()
{
    std::cout << "123\n";
}

void testclass::print()
{
    std::cout << "this is testcalss\n";
}

之后设置为启动项目,生成就可以得到lib文件:

生成lib

【输出】-【生成】可以看到目录

生成

LIB使用-引用

使用:新建空项目,添加引用,创建一个头文件把之前头文件的东西复制进来

引用&头文件

新建一个main.cpp

#include <iostream>
#include "MyLIB.h"

int main()
{
    fun(4);
    std::cout << k << std::endl;
    testclass tc;
    tc.print();
    return 0;
}
LIB使用-复制LIB文件

找到lib文件,复制到main.cpp目录下,复制头文件过来,复制#pragma comment(lib, "lib.lib")到main.cpp文件中main函数上面即可。

ANTLR的lib生成

antlr4cpp-antlr2015这个项目属性里面改成配置类型-静态库,生成后复制得到的lib文件到自己的项目目录下。

复制antlr4-runtime.h等所有头文件到自己的项目目录下。

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值