一文了解 Yacc、Lex、JavaCC、ANTLR 等编译器相关概念

createh53个月前 (01-21)技术教程39


Compiler

定义一种“上下文无关文法”(context-free grammar,CFG),然后写一个 C 程序来解释这种 CFG,那么这个 C 程序就叫做“编译器”(compiler)。只不过这个编译器只能编译特定的 CFG,就像 g++ 只能编译 C++,javac 只能编译 Java 代码,这些都是编译器。

CC

CC 即 compiler-compiler,意思是“编译器的编译器”,另外还可以叫做 compiler generator。

对于任意给定的 CFG,如果可以写出一个 C 程序,生成另一段 C 程序代码,这段 C 程序代码是给定 CFG 的编译器。那么,这个 C 程序就叫做 CC。

Yacc、Bison

Yacc 即 Yet Another Compiler-Compiler,是经典的生成语法分析器的工具,将任何一种编程语言的所有语法翻译成针对此种语言的 Yacc 语法解析器。

Yacc 采用自下而上(LALR)语法分析方法,输入是巴科斯范式(Backus-Naur Form,BNF)表达的语法规则以及语法规约的处理代码,输出的是基于表驱动的编译器,包括输入的语法规约的处理代码部分。

Yacc 最初由 AT&T 的 Steven C. Johnson 为 Unix 操作系统开发,后来一些兼容程序如 Berkeley Yacc(byacc)、GNU Bison 相续出现。它们在原先基础上做了一些改进或者扩展,但基本概念是相通的。

GNU Bison 是 Yacc 的 GNU 自由软件版本,基本兼容 Yacc,并做了一些改进。在新近版本中,除了与 Yacc 相同的 LALR 语法分析,Bison 还增加了对 GLR(Generalized LR) 语法分析的支持。

Lex、Flex

Lex 是 LEXical compiler 的缩写,是一个词法分析器(scanner)的生成工具,它使用正则表达式(regular expression)来描述各个词法单元的模式,由此给出一个词法分析器的规约,并生成相应的实现代码。 Lex 程序的输入方法称为 Lex 语言,而 Lex 程序本身被称为 Lex 编译器。

Yacc 生成的编译器主要是用 C 语言写成的语法解析器(Parser),需要与词法分析器一起使用(一般为 Lex),再把两部分产生的 C 程序代码一起编译。描述词法分析器的文件 *.l,经过 Lex 编译后,生成一个 lex.yy.c 的文件,然后由 C 编译器编译生成一个词法分析器。词法分析器,简单来说,其任务就是将输入的各种符号,转化成相应的标识符(token),转化后的标识符很容易被后续阶段处理。

Flex 是 Lex 的开源版本,是 Lex 编译器的一种替代实现。

JavaCC

JavaCC 即 Java Compiler Compiler,是开源、轻量的语法分析器生成器和词法分析器生成器,采用纯 Java 编写,可生成 Java、C++ 和 C# 代码。ANTLR 根据输入的文法生成由 Java 语言编写的分析器,相当于 Java 界的 Yacc + Lex 或 Bison + Flex。

和 YACC 类似,JavaCC 由(Extended Backus-Naur Form,EBNF) 格式的形式文法生成语法分析器。不同的是,JavaCC 生成的是自顶向下 LL 语法分析器对 CFG 进行解析。同时,JavaCC 生成词法分析器的方式也和 Lex 很像。JavaCC 还提供 JJTree 帮助使用者构建语法树,JJDoc 工具为源文件生成 BNF 范式文档。

JavaCC 源自著名的 Sun 公司。1996 年,Sun 推出了一个名为 Jack 的语法解析器生成器。后来,负责“Jack”的开发者创办了自己的公司 Metamata,并将 Jack 改名为 JavaCC。Metamata 最后成为了WebGain 的一部分,后 WebGain 关闭。目前 JavaCC 代码以 BSD 许可证托管在 GitHub。

很多著名开源项目用到了 JavaCC,包括:

  • Apache ActiveMQ
  • Apache Zookeeper
  • Apache Lucene
  • Apache Tomcat
  • Apache Avro
  • Apache Camel
  • Apache Calcite

ANTLR

ANTLR 即 ANother Tool for Language Recognition,是基于自顶向下的递归下降 LL 算法实现的语法解析器生成器(parser generator),采用纯 Java 语言编写。ANTLR 能够自动生成解析器,并将用户编写的 ANTLR 语法规则直接生成目标语言的解析器。所生成的解析器客户端将输入的文本生成抽象语法树,并提供遍历树的接口,以访问文本的各个部分。

ANTLR 是 Terence Parr 在普渡大学攻读硕士学位时的创作,在著名编译器领域大师 Hank Dietz 教授的指导下,开始研究构造自动化的分析器。1993年,Parr 取得博士学位,并于同年发布 ANTLR 1.10 版。最早的 ANTLR 只支持 Java, 直到 ANTLR 3 以后开始支持 Ada95、C、C#、JavaScript、Objective-C、Perl、Python、Ruby、C++ 和 Standard ML。

ANTLR 生成的代码与使用递归下降法(构造手工分析器的主要方法)产生的代码非常相似,便于程序员阅读和理解,与 Yacc 产生的晦涩代码相比进步了很多。与 JavaCC 相比,ANTLR 功能更加全面,开箱即用,另外支持语言更丰富,不止局限于 Java 语言。

使用 ANTLR 的著名项目包括:

  • Groovy
  • Jython
  • Hibernate
  • Apache Cassandra
  • WebLogic Server
  • 相关文章

    【Java基础】Java中方法的定义和调用

    “这里是云端源想IT,帮你轻松学IT”嗨~ 今天的你过得还好吗?你要看过世界辽阔再去评判是好是坏- 2023.08.07 -Java语言中的方法Method在其他语言当中也可能被称为函数Functio...

    Java-自定义lambda函数(自定义java.lang.string)

    自定义lambda函数在 Java 中,可以通过定义函数式接口来创建自定义的 Lambda 函数。函数式接口是一个只包含单个抽象方法的接口,可以使用 Lambda 表达式来实现这个接口。以下是如何定义...

    「软帝学院」什么是java?学Java能做什么?Java有什么特性?

    什么是java?学Java能做什么?Java有什么特性?Java 技术既是一种高级的面向对象的编程语言,也是一个平台。Java 技术基于 Java 虚拟机(Java virtual machine,J...

    带你认识Java——这一语言(java是什么语言的一个实例)

    1、JavaJava是一门面向对象的编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象...

    JAVA自定义注解(java自定义注解记录日志)

    JAVA自定义注解注解概念注解是Java SE 5.0版本开始引入的概念,它是对java源代码的说明,是一种元数据(描述数据的数据)。注解和注释的不同注释 注释是对代码的说明,给代码的读者看,便于帮读...

    Java应该怎么学?请查收这份学习指南

    Java作为计算机行业中的常用语言,不管是想就业还是提升自我,学习Java都是一个不错的选择,但是很多人在刚接触Java时,都不知道Java应该怎么学,别担心,这里小编详细为大家解答Java的学习方...