/***********************************************************/
>我使用的测试jjt,jj文件来自于javacc5.0版本
>dir_hier/javacc-5.0/javacc-5.0/examples/
JJTreeExamples
SimpleExamples
/***********************************************************/

/***********************************************************/
0.javacc(the java Compiler Compiler)概要
>Abstract summary:
javacc一般用于编写某种语言的书写规则,如java的语法规则
变量必须以字母或者$开头或者以数字结尾等,这是一种书写规范,
书写规范是这门语言特有的,他必须满足,那么他是怎么去判断
书写的字符窜符合了规则了,那就需要进行验证,javacc就是
一种用于定义某种特定输入格式字符窜规则的工具,也是验证这种
特定格式字符窜的验证者。定义字符窜输入格式,以及验证输入的
字符窜是javacc的最基本作用。
javacc语法规则描述文件的书写方式有两种一种是一种是.jj文件,
另外一种是.jjt文件,两种文件的书写方式差异性不大,但是jjt文件
比jj文件表达语法规则更加容易,jj文件的可选参数项和jjt有很大的
不同,这是他们最大的区别。
/***********************************************************/

/***********************************************************/
1.javacc语法规则书写操作基本代码
>如何在生产表达式中写条件结构
(
term = < TERM >
|
term = < STAR >
|
term = < PREFIXTERM >
|
term = < WILDTERM >
|
term = < NUMBER >
)
>生成后的代码对应到
分析:
因为在javacc中(<A> | <B>)被表示成了在两个规则中任意选择一个的意思。
switch(tokenkind){
case TERM:
/** doSomthing...*/
break;
case STAR:
/** doSomthing...*/
break;
...
}

void ifExp():{int k=0;/** java局部变量声明处*/}{
{/*在{}中写任意的java代码并且是以面向对象的方式*/}
(
{
if(k==2){break;}
System.out.println("k="+k);
k++;
}
)*
}
>如何在生产表达式中写循环结构
->(
{
if(k==2){break;}
System.out.println("k="+k);
k++;
}
->)*

>生成对应的代码
while(true){
if(k==2){
break;
}
System.out.println("k="+k);
k++;
}

>在生产表达式中调用其他的生产表达式
对应到java中的方法调用
void B():
{
StringBuffer sb = new StringBuffer();
Token t = null;
}{
t = A /** 这里对应生成的java代码t=jj_consume_token(A);
* 因为等于就是要消费一个记号把消费的这记号的应用给t变量
*/
}
void A():{}{}

>javacc中的词法状态介绍
<*>TOKEN:{}
<DEFAULT>TOKEN:{<A:"2001 TO 2002">:DateRange
|
<B:"anything">
}
<DateRange>TOKEN:{}
解析:<*>,<DEFAULT>,<DateRange>是词法状态
定义词法状态的好处是,如果在生产表达式中
正好有一个字符窜匹配到了2001 TO 2002这个字符窜
那么他就会马上把下一个要匹配的模式字符窜定义
为DateRange这种词法状态中定义的Token

>有了循环有了条件结构有了定义变量的方式
javacc语法文件就相当完美了。
/***********************************************************/

/***********************************************************/
2.JJT语法规则描述文件书写方法
>jjt概要
jjt能够很清晰的表达出语法分析的思路,
并且他把每一个生产表达式都作为一个节点来表示,
将这些节点的执行顺序有效的组织成了一颗语法分析树

>.options
>BUILD_NODE_FILES (default: true)
为SimpleNode以及语法中使用的其它节点创建样本实现。

>MULTI(default: false)
创建多模式解析树。
此选项默认为False,生成一个单一模式解析树。

>NODE_DEFAULT_VOID (default: false)
此选项设置为True时,
不在使每个非包装产生式定义一个节点,取而代之为空。

>NODE_FACTORY (default: false)
用下面的方式使用一个工厂方法创建一个节点:
public static Node jjtCreate(int id)

>NODE_PACKAGE (default: "")
被放进生成节点类里的包。默认为解析器的包。

>NODE_PREFIX (default: "AST") AST意思为抽象节点
在多模式中,前缀用来从节点标志符构造节点类名字。
默认前缀为” AST”

>NODE_SCOPE_HOOK (default: false)
在节点作用域入口和出口处插入调用用户自定义的解析方法。
在节点的生命开始和结束之前需要调用的方法被成为钩子。
参见:节点作用域钩子。

>NODE_USES_PARSER (default: false)
是否将当前解析器对象也出入到节点对象的属性中
JJTree会使用一个选择的形式将解析对象传给构造函数。例如:
public static Node MyNode.jjtCreate(MyParser p, int id);
MyNode(MyParser p, int id);

>STATIC (default: true)
为静态解析器生成代码。
选项默认为True。
这必须一致的通过等效的JavaCC选项被使用。
选项的值发布于JavaCC的源码中。

>VISITOR (default: false)
在节点类中插入jjtAccept()方法,
为语法中使用的每个节点类型产生一个访问者实现。

>VISITOR_EXCEPTION (default: "")
如果这个选项被设置,它将使用jjtAccept()和visit()方法的形式。
注意:这个选项将会在以后的某个JJTree版本中删除。如果不影响你请不要使用它。

>JJTREE_OUTPUT_DIRECTORY (default: use value of OUTPUT_DIRECTORY)
默认情况下,在全局OUTPUT_DIRECTORY设置中指定JJTree生成的输出目录。
明确的设置这个选项允许用户从树文件中分离解析器。
/***********************************************************/

/***********************************************************/
3.语法分析树节点(Node)
>javacc把每一个生产表达式都看作为一个简单节点(SimpleNode)在默认
MULTI(default: false)的情况下,javacc已经提供了这个SimpleNode类的简单实现。
>MULTI(default: true)将为每一个节点都按照[NODE_PREFIX_生产表达式的名字]这样
一种形式来提供默认的简单实现类。
>定义节点的方式
明确定义:一个以指定子节点数创建的节点
void AdditiveExpression() #void : {}
{
(
MultiplicativeExpression()
(
( "+" | "-" )MultiplicativeExpression()
)*
)#Add(3)
}

>语法分析树参考结果:
Add
Integer
Integer
Integer

>#void不会为这个生产表达式生成对应的节点
>#Add表示在循环执行过程中生成的所有节点中的前三个节点作为
以Add为命名的儿子节点。

按照条件定义:
void AdditiveExpression() #void : {}
{
(
MultiplicativeExpression()
(
( "+" | "-" ) MultiplicativeExpression()
)*
) #Add(>3)
}
>#Add(>1)另外一种写法#Add(jjtree.arity() > 1)
生成的源码:
jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1);
在执行循环过程中创建的节点个数大于1的话就会将所有的节点
做为Add的子节点然后将Add节点添加到堆栈中,如果条件不满足
那么创建的所有节点将会保留在栈中默认会在做为上一个节点的
子节点
>语法分析树参考结果:
Start /** 因为在执行循环过程中创建的节点数没有达到指定的个数所以是start*/
Integer
Integer

>notes:
( ... ) #N ( a() )
上面表达式逻辑不清,
你必须明确的使用条件式:
( ... ) #N(true) ( a() )

>为产生式的节点指定名称
void ProductExp() #MyNode:{} {//doAnything}
#MyNode为这个生产表达式所对应的节点的名称

>特殊应用
void P3():{}
{
P4() ( P5() )+ #ListOfP5s P6()
}
#name=jjtree.closeNodeScope(jjtn001, true);
#name(3)=jjtree.closeNodeScope(jjtn001, 3);
#name(>3)=jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1);

>什么是jjThis
ASTStart Start() : {}
{
Expression() ";"
{ return jjtThis; }
}
分析:
jjThis代表了当前节点的引用地址,
就好像ASTStart Start()这个生产表达式对应到Start这个
节点那么jjtThis就指向了这个对象,
在其内部的实现代码为:
ASTStart jjtn000 = new ASTStart(JJTSTART);

>什么是NODE_SCOPE_HOOK="true"(默认为true表示有钩子)
这个名气叫的很有味,钩子,正好是在某个节点被创建的
时候调用指定的钩子方法,在节点添加到栈的时候要调用的方法
钩子在open的时候可以做一些预备工作,结束可以做一些后续工作
示例代码:
static final public void AdditiveExpression() throws ParseException {
ASTAdd jjtn001 = new ASTAdd(JJTADD);// 创建节点
boolean jjtc001 = true;
jjtree.openNodeScope(jjtn001); // 这就是钩子
try {
//do something...
} finally {
if (jjtc001) {
jjtree.closeNodeScope(jjtn001, 3);// 这就是钩子
}
}
}
/***********************************************************/
4.jjt文件生成的文件解析
SimpleQueryParser.jjt

SimpleQueryParser.jj

JJTSimpleQueryParserState.java
Node.java
ParseException.java
SimpleCharStream.java
SimpleNode.java
SimpleQueryParser.java
SimpleQueryParserConstants.java
SimpleQueryParserTokenManager.java
SimpleQueryParserTreeConstants.java
Token.java
TokenMgrError.java

>jjt文件可以生成.jj文件

>SimpleQueryParser这个名字在很多类名中都以重复的字眼出现,这是通过
Parser_Begin(SimpleQueryParser)...Parser_End(SimpleQueryParser)
指定的。

>JJTSimpleQueryParserState.java用于记录节点的组织情况
这个类有单独的说明,在JJTSimpleQueryParserState.java
中,他是一个以堆栈形式设计的类。

>Node.java是一个接口jjt中节点必须实现他,在选项MULTI(default: false)
的时候javacc编译器已经帮我们简单的做了实现这个类为SimpleNode.java。

>ParseException.java在语法分析的时候遇到不符合规则的字符时抛出的异常

>SimpleQueryParserConstants.java这个类主要用于关联定义的Token

>SimpleQueryParserTreeConstants.java主要用于关联定义的节点
如果没有给生产表达式命名那么他默认就是用生产表达式的名字做为节点的
名字

>SimpleQueryParserTokenManager.java这是最重要的类他用于生产Token对象
在getNextToken()中体现了这么一点

>Token.java这个对象作为最小的记号单元用于封装SimpleQueryParserTokenManager
生成的记号

>SimpleQueryParser.java将类综合起来提供语法分析服务,他是消费Token对象的,
在jj_consume_Token(token_kind)中可以体现这一点,传入一个记号的类型返回这个
类型的一个token对象

>TokenMgrError.java在生产Token对象的过程中遇到错误

>SimpleCharStream.java用于封装输入的字符窜

>SimpleQueryParserTokenManager.java/**用于产生Token*/
SimpleQueryParserTokenManager.getNextToken()/** 生产Token的方法*/

/** 消费Token的SimpleQueryParser利用这些Token生成特定的逻辑对象*/
SimpleQueryParser.java
SimpleQueryParser.jj_consume_token(int kind);/** 根据指定的类型消费一个token*/
SimpleQueryParser.jj_ntk()/** 如果当前jj_ntk变量为-1
说明当前token对像的下一个token没有找到需要接着要到tokenmanage里面
拿一个token出来作为当前token的next*/

/***********************************************************/

/***********************************************************/
5.jj文件写法解析
>options
>STATIC=false;
意思所有的生产表达式对应到java代码的时候
不是静态的
/***********************************************************/

转载:http://blog.csdn.net/zyb243380456/article/details/7240225

javacc jjtree 写法 以及 jj写法 基本语法 以及应用的更多相关文章

  1. CSS- ie6,ie7,ie8 兼容性写法,CSS hack写法

    css ie6,ie7,ie8 兼容性写法,CSS hack写法 margin-bottom:40px;       /*ff的属性*/margin-bottom:140px\9;    /* IE6 ...

  2. C++ //多态案例 -计算器类(普通写法 和 多态写法) //利用多态实现计算器 //多态好处: //1.组织结构清晰 //2.可读性强 //3.对于前期和后期扩展以及维护性高

    1 //多态案例 -计算器类(普通写法 和 多态写法) 2 3 #include <iostream> 4 #include <string> 5 using namespac ...

  3. (转载)robots.txt写法大全和robots.txt语法的作用

    1如果允许所有搜索引擎访问网站的所有部分的话 我们可以建立一个空白的文本文档,命名为robots.txt放在网站的根目录下即可.robots.txt写法如下:User-agent: *Disallow ...

  4. robots.txt写法大全和robots.txt语法的作用

    1如果允许所有搜索引擎访问网站的所有部分的话 我们可以建立一个空白的文本文档,命名为robots.txt放在网站的根目录下即可.robots.txt写法如下:User-agent: *Disallow ...

  5. sql查询一天内的where写法,sql写法

    sql查询一天内的写法: 1. where createtime BETWEEN (select date_format(now(),'%Y-%m-%d 00:00:00')) and (select ...

  6. 背景图片等比缩放的写法background-size简写法

    1.背景图片或图标也可像img一样给其宽高就能指定其缩放大小了. 比如一个实际宽高36*28的图标,要缩小一半引用进来的写法就是: background:rgba(0, 0, 0, 0) url(&q ...

  7. mschart asp chart 用法,包括前台写法与后台写法,还有click事件,如何触发。

    纯后台动态生成aspchart ,这种方式没办法实现chart中click事件.click事件点击没有反应,用第二种可以实现点击事件. 两种方式实现同一种效果图: 第一种写法:后台动态生成aspcha ...

  8. ajax的jquery写法和原生写法

    一.ajax的简介 Ajax被认为是(Asynchronous(异步) JavaScript And Xml的缩写).现在,允许浏览器与服务器通信而无须刷新当前页面的技术都被叫做Ajax. 同步是指: ...

  9. JUC 并发编程--02,生产者和消费者 synchronized的写法 , juc的写法. Condition的用法

    synchronized的写法 class PCdemo{ public static void main(String[] args) { //多个线程操作同一资源 Data data = new ...

随机推荐

  1. 【CentOS】Eclipse插件egit使用

    1.简介 2.安装 3.配置 4.使用 5.补充说明   参考资料: http://yufenfei.iteye.com/blog/1750124    1.简介     EGit就是一款Eclips ...

  2. Poj 1050 分类: Translation Mode 2014-04-04 09:31 103人阅读 评论(0) 收藏

    To the Max Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39058   Accepted: 20629 Desc ...

  3. 项目分析 NGPcontext

    NGPcontext 之前对这个一直很疑惑,我一直认为只是在机器人方面有用处,但很有疑问,正在做这方面,我想好好看看到底是怎么运行的 bool NGP::init(NGPcontext context ...

  4. Centos最小化安装后联网配置

    Centos最小化安装默认不开启网络,只需进行简单配置就可以上网了. 1.  查看/etc/sysconfig/network-scripts/下面的文件,这里会有一个ifcfg-en******(这 ...

  5. [ActionScript 3] 本地安全沙箱问题最快解决方法

    使用FLex4.0时, Chrome等浏览器会报 安全水箱问题.....   解决方案: 打开flash全局安全配置面板并在页面中的配置面板中添加可信任的swf文件或者文件夹: 若是记不住全局安全配置 ...

  6. 也可以使用如下命令更改您的默认 Shell

    也可以使用如下命令更改您的默认 Shell chsh -s /bin/zsh (需要输入您的密码)

  7. SQLServer中查询的数字列前面补0返回指定长度的字符串

    SQLServer中查询的数字列前面补0返回指定长度的字符串: 如: 角本如下: /****** Script for SelectTopNRows command from SSMS ******/ ...

  8. 一篇不错的讲解Java异常的文章(转载)

    http://www.blogjava.net/freeman1984/archive/2007/09/27/148850.html 六种异常处理的陋习 你觉得自己是一个Java专家吗?是否肯定自己已 ...

  9. Log4Net 全方位跟踪程序运行

    原文:http://kb.cnblogs.com/page/100968/ 1.Log4Net 简单使用 使用Log4net必须引入log4net.dll 文件,因为log4net 是开源的,所以可以 ...

  10. 由枚举模块到ring0内存结构 (分析NtQueryVirtualMemory)

    是由获得进程模块而引发的一系列的问题,首先,在ring3层下枚举进程模块有ToolHelp,Psapi,还可以通过在ntdll中获得ZwQuerySystemInformation的函数地址来枚举,其 ...