实验一:javacc学习笔记

本文介绍了JavaCC,一个用于生成词法分析器和解析器的工具。内容包括JavaCC的工作原理、主要工具如javaCC、jjTree和jjDoc的用途,以及解决分析冲突的策略,如LL(1)语法和LOOKAHEAD提示。此外,还概述了jj文件的结构和组成部分。
摘要由CSDN通过智能技术生成

一、概念
JavaCC(Java Compiler Compiler)是一个用JAVA开发的受欢迎的语法分析生成器。这个分析生成器工具可以读取上下文无关且有着特殊意义的语法并把它转换成可以识别且匹配该语法的JAVA程序。
JavaCC本身并不是一个词法分析器或者解析器而是一个代码生成器,这意味着它可以根据输入的语言定义输出一个词法分析器和解析器。JavaCC输出的代码是合法的可编译Java代码。
词法分析器工作流程:

语法分析器工作流程:

二、三个工具
javaCC 用来处理语法文件(jj)生成解析代码;
jjTree 用来处理jjt文件,生成树节点代码和jj文件,然后再通过javaCC生成解析代码;
jjDoc 根据jj文件生成bnf范式文档(html)。这三个工具都十分重要,分别贯穿着编写时的过程。
三、缺陷
javacc采用的是自顶向下的分析方法,而且没有回溯功能,因此如何解决冲突的问题,是程序员的责任。
必须要解决两个问题:左递归和公因子
关于左递归的问题,一般采用经典的修改文法的方法解决。
关于公因子的问题,可以改写算法(提取公因子),也可以通过展望(look ahead)更多符号的方法来解决。 但是因为javacc扩展了经典的BNF,因此它面临更多的问题。总之,当在编译时碰到冲突问题时,就说到了一个choice point。
可以将javacc中choice point归结为以下几类:
l . 由选择算子 | 引入的冲突,
2. 由可省略算子 [] 或 ?引入的冲突
3. 由重复算子 * 引入的冲突
4. 由重复算子 + 引入的冲突

当在javacc中碰到冲突时,可以采用下面的方法之一解决问题
修改语法,使之成为LL(1)语法。这个方法有一个问题:修改后的语法可能非常不直观了
在jj文件中给javacc一些提示。这些提示可以根据展望的作用域分成全局提示和部分提示。要采用全局提示,只要将LOOKAHEAD=k写到Options块中即可(当然也可以写到javacc的命令行里),这样javacc产生的分析器就可以分析LL(K)语法生成的语言。也可以设置一个局部的LOOKAHEAD,这样既保持了LL(1)的高效性,又可以解决choice point中的。LOOKAHEAD的局部声明形式是LOOKAHEAD(…),其中括号中的可以是数字(说明向后看多少个记号),或者是一个表示文法的串(当成功时选择)。LOOKAHEAD的完整形式为LOOKAHEAD(amount, expansion, {java语言里的逻辑表达式}),它的含义是,如果到达amount个记号后,expansion如果仍然成立,且逻辑表达式也成立,则执行下面的展开。

采用第一种方法的好处是效率非常高,易于维护。采用第二种方法的好处是语法更加直观,但是却不易维护。有时候采用第一种方法是无法解决冲突的,第二种方法是唯一的选择。
四、工作过程
javaCC在使用的时候会首先创建一个JJ文件。这个语法文件以一些JavaCC所提供的Options的参数设置开始。在这个例子中,Options的参数都是它们的默认值。因此,这些参数实际上是不需要的。程序员甚至可以完全忽略Options这一部分,或者省略其中的一个或多个Options的参数,详细的关于Options的参数设置的问题请参考JavaCC的文档。
接下来的是一个处在”PARSER_BEGIN(name)”和”PARSER_END(name)”中间的编译单元。这个编译单元可以是任意的复杂。在这个编译单元中唯一的限制就是它必须定一个一个叫”name”的类——与PARSER_BEGIN和PARSER_END的参数的相同。这个”name”被用作语法分析产生器生成的java文件的前缀。
JavaCC的输入文档是一个词法和语法的规范文件,其中也包括一些动作的描述,它的后缀应该是jj。

简而言之,一个jj文档由下面几个部分构成:
(1)Options{}部分:这个部分对产生的语法分析器的特性进行说明,例如向前看的token的个数(用来解除冲突)。这一部分是可以省略的,因为每一个选项都有默认值,当我们没有对某个选项进行说明时,它就采用默认值。也可以把这些选项作为javacc命令的参数来启动javacc,可以达到同样的效果。
(2)分析器类的声明:这个部分指定了分析器类的名字,以及其他类中成员的声明。这个部分是必须有的。这个部分的声明如下:
PARSER_BEGIN(classname)
Class classname {
……
}
PARSER_END(classname)
(3)词法部分声明:这里面有四类:SKIP、TOKEN、SPECIAL_TOKEN、MORE。其中,SKIP用来说明被忽略的串,下面是一个例子:
SKIP {
“ “
|
“\n”
|
“\r”
}
TOKEN用来说明在词法层次上识别的token,下面是一个例子:
TOKEN {

/**
 * the javacc file of CMM
 * By huxijie 2014302580184
 */
options
{
  static = 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值