ImageVerifierCode 换一换
你正在下载:

javacc.docx

[预览]
格式:DOCX , 页数:13 ,大小:20.05KB ,
资源ID:11982448      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11982448.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(javacc.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

javacc.docx

1、javaccjavacc前言本系列的文章的宗旨是让大家能够写出自己的编译器,解释器或者脚本引擎,所以每到理论介绍到一个程度后,我都会来讨论实践问题.理论方面,编译原理的教材已经是够多了,而实践的问题却很少讨论.前几节文章只讨论到了词法分析和LL文法分析,关键的LR文法分析这里却还没有讲,我们先不要管复杂的LR文法和算法,让我们使用LL算法来实际做一些东西后再说.本文将介绍一个在JAVA上广泛使用的LL算法分析工具Javacc.(这是我唯一能找到的使用LL算法的语法分析器构造工具).这一节的文章并非只针对JAVA开发者,如果你是C/C+开发者,那么也请你来看看这个JAVA下的优秀工具,或许你将来

2、也用得着它.Lex和yacc这两个工具是经典的词法分析和语法分析工具,但是它们都是基于C语言下面的工具,而使用JAVA的朋友们就用不上了.但是JAVA下已经有了lex和yacc的替代品javacc(Java Compiler Compiler ).同时javacc也是使用LL算法的工具,我们也可以实践一下前面学的LL算法.首先声明我不是一个JAVA专家,我也是刚刚才接触JAVA.Java里面或许有很多类似javacc一样的工具,但是据我所知,javacc还是最广泛,最标准的JAVA下的词法语法分析器.Javacc的获取同lex和yacc一样,javacc也是一个免费可以获取的通用工具,它可以在

3、很多JAVA相关的工具下载网站下载,当然,javacc所占的磁盘空间比起lex和yacc更大一些,里面有标准的文档和examples.相对lex和yacc来说,javacc做得更人性化,更容易一些.如果你实在找不到javacc,还是可以联系我,我这里有.现在最新的就是javacc 3.2版本.Javacc的原理Javacc可以同时完成对text的词法分析和语法分析的工作,使用起来相当方便.同样,它和lex和yacc一样,先输入一个按照它规定的格式的文件,然后javacc根据你输入的文件来生成相应的词法分析于语法分析程序.同时,新版本的Javacc除了常规的词法分析和语法分析以外,还提供JJTr

4、ee等工具来帮助我们建立语法树.总之,Javacc在很多地方做得都比lex和yacc要人性化,这个在后面的输入文件格式中也能体现出来.Javacc的输入文件Javacc的输入文件格式做得比较简单.每个非终结符产生式对应一个Class中的函数,函数中可以嵌入相应的识别出该终结符文法时候的处理代码(也叫动作).这个与YACC中是一致的.Javacc的输入文件中,有一系列的系统参数,比如其中lookahead可以设置成大于1的整数,那么就是说,它可以为我们生成LL(k)算法(k=1),而不是简单的递归下降那样的LL(1)算法了.要知道,LL(2)文法比起前面讨论的LL(1)文法判断每个非终结符时候需

5、要看前面两个记号而不是一个,那么对于文法形式的限制就更少.不过LL(2)的算法当然也比LL(1)算法慢了不少.作为一般的计算机程序设计语言,LL(1)算法已经是足够了.就算不是LL(1)算法,我们也可以通过前面讲的左提公因式把它变成一个LL(1)文法来处理.不过既然javacc都把lookahead选择做出来了,那么在某些特定的情况下,我们可以直接调整一个lookahead的参数就可以,而不必纠正我们的文法.下面我们来看看Javacc中自带的example中的例子.例5.1这个例子可以在javacc-3.2/doc/examples/SimpleExamples/Simple1.jj看到PAR

6、SER_BEGIN(Simple1)public classSimple1 public static void main(String args) throwsParseException Simple1 parser = new Simple1(System.in); parser.Input(); PARSER_END(Simple1)void Input() : MatchedBraces()(n|r)* voidMatchedBraces() : MatchedBraces() 设置好javacc的bin目录后,在命令提示符下输入javacc Simple1.jj然后javacc就会

7、为你生成下面几个java源代码文件Simple1.javaSimple1TokenManager.javaSimple1Constants.javaSimpleCharStream.javaToken.javaTokenMgrError.java其中Simple1就是你的语法分析器的对象,它的构造函数参数就是要分析的输入流,这里的是System.in. class Simple1就定义在标记PARSER_BEGIN(Simple1)PARSER_END(Simple1)之间.但是必须清楚的是,PARSER_BEGIN和PARSER_END中的名字必须是词法分析器的名字(这里是Simple1).

8、PARSER_END下面的定义就是文法非终结符号的定义了.Simple1的文法基本就是:Input - MatchedBraces (n|r)*MatchedBraces- “ MatchedBraces “”从它的定义我们可以看到,每个非终结符号对于一个过程.比如Input的过程void Input() : MatchedBraces()(n|r)* 在定义void Input后面记住需要加上一个冒号”:”,然后接下来是两个块的定义.第一个中的代码是定义数据,初试化数据的代码.第二个中的部分就是真正定义Input的产生式了.每个产生式之间用”|”符号连接.注意: 这里的产生式并非需要严格BN

9、F范式文法,它的文法既可以是BNF,同时还可以是混合了正则表达式中的定义方法.比如上面的 Input - MatchedBraces (n|r)*中(“n”|”r”)* 就是个正则表达式,表示的是n或者r的0个到无限个的重复的记号.而是javacc系统定义的记号(TOKEN),表示文件结束符号.除了,无论是系统定义的TOKEN,还是自定义的TOKEN, 里面的TOKEN都是以的方式表示.每个非终结符号(Input和MatchedBraces)都会在javacc生成的Simple1.java中形成Class Simple1的成员函数.当你在外部调用Simple1的Input,那么语法分析器就会开

10、始进行语法分析了. 例5.2在javacc提供的example里面没有.javacc提供的example里面提供的例子中SimpleExamples过于简单,而其它例子又过于庞大.下面我以我们最常见的数学四则混合运算的文法来构造一个javacc的文法识别器.这个例子是我自己写的,十分简单,.其中还包括了文法识别同时嵌入的构建语法树Parse-Tree的代码.不过由于篇幅的原因,我并没有给出全部的代码,这里只给了javacc输入部分相关的代码.而Parse-tree就是一个普通的4叉树,3个child,1个next(平行结点),相信大家在学习数据结构的时候应该都是学过的.所以这里就省略过去了.在

11、大家看这些输入代码之前,我先给出它所使用的文法定义,好让大家有个清楚的框架.Expression -Term Addop Term Addop - +| -Term - Factor Mulop Factor Mulop - *| /Factor - ID| NUM | (Expression )这里的文法可能和BNF范式有点不同.的意思就是0次到无限次重复,它跟我们在学习正则表达式的时候的”*”符号相同,所以,在Javacc中的文法表示的时候,部分的就是用()*来表示.为了让词法分析做得更简单,我们通常都不会在文法分析的时候,使用”(”,”)“等字符号串来表示终结符号,而需要转而使用LPAR

12、EN, RPAREN这样的整型符号来表示.PARSER_BEGIN(Grammar)public class Grammar implements NodeType publicParseTreeNode GetParseTree(InputStream in) throws ParseException Grammar parser =new Grammar(in); return parser.Expression(); PARSER_END(Grammar)SKIP : | t | n | rTOKEN : | | | | | | | ParseTreeNode Expression()

13、 : ParseTreeNodeParseTree = null; ParseTreeNodenode; (node=Simple_Expression() if(ParseTree = null) ParseTree =node; else ParseTreeNode t; t= ParseTree; while(t.next != null) t=t.next; t.next = node; )* returnParseTree;ParseTreeNode Simple_Expression() : ParseTreeNodenode; ParseTreeNodet; intop;node

14、=Term() ( op=addop()t=Term() ParseTreeNodenewNode = new ParseTreeNode(); newNode.nodetype= op; newNode.child0= node; newNode.child1= t; switch(op) casePlusOP: newNode.name= Operator: +; break; caseMinusOP: newNode.name= Operator: -; break; node= newNode; )* returnnode; int addop() : return PlusOP; |

15、 return MinusOP; ParseTreeNode Term() : ParseTreeNodenode; ParseTreeNodet; intop;node=Factor() ( op=mulop()t=Factor() ParseTreeNodenewNode = new ParseTreeNode(); newNode.nodetype= op; newNode.child0= node; newNode.child1= t; switch(op) caseTimersOP: newNode.name= Operator: *; break; caseOverOP: newN

16、ode.name= Operator: /; break; node= newNode; )* return node; int mulop() : return TimersOP; | return OverOP; ParseTreeNode Factor() : ParseTreeNodenode; Tokent;t= node=new ParseTreeNode(); node.nodetype= IDstmt; node.name = t.image; return node; |t= node=new ParseTreeNode(); node.nodetype= NUMstmt;

17、node.name = t.image; node.value= Integer.parseInt(t.image); return node; | node=Simple_Expression() return node; 其中SKIP 中的定义就是在进行词法分析的同时,忽略掉的记号.TOKEN中的,就是需要在做词法分析的时候,识别的词法记号.当然,这一切都是以正则表达式来表示的.这个例子就有多个非终结符号,可以看出,我们需要为每个非终结符号写出一个过程.不同的非终结符号的识别过程中可以互相调用. 以Simple_Expression()过程为例,它的产生式是Expression- Term

18、 addop Term ,而在javacc的输入文件格式是,它的识别是这样写的node=Term() ( op=addop()t=Term() )* 前面说过,这里的”*”符号和正则表达式是一样的,就是0次到无限次的重复.那么Simple_Expression等于文法Term Addop Term Addop Term Addop Term 而Addop也就相当于PLUS和MINUS两个运算符号.这里我们在写Expression的文法的时候,同时还使用了赋值表达式,因为这个和Yacc不同的时候,Javacc把文法识别完全地做到了函数过程中,那么如果我们要识别Simple_Expression的

19、文法,就相当于按顺序识别Term和Addop两个文法,而识别那个文法,就相当于调用那两个非终结符的识别函数.正是这一点,我觉得Javacc的文法识别处理上就很接近程序的操作过程,我们不需要像YACC那样使用严格的文法表示格式,复杂的系统参数了.关于Yacc的使用,其实比Javacc要复杂,还需要考虑到和词法分析器接口的问题,这个我会在以后细细讲到.至于其它的文法操作解释我就不再多说了,如果要说,就是再写上十篇这样的文章也写不完.本文只能给读者们一个方向,至于深入的研究,还是请大家看javacc提供的官方文档资料.最后由于国外使用JAVA做项目的程序员比国内多,那么讨论JAVA技术的人员也比较多.可能来这里读我的文章的人都是C/C+程序员,但是关注其它领域同方向的技术也是可以让我们的知识领域更加宽广.关于JavaCC的讨论主要是在国际新闻组pilers.tools.javacc如果大家在使用JavaCC做实际问题的时候遇到什么问题,不妨上去找找专家.

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1