Antlr简介及中文手册.doc
《Antlr简介及中文手册.doc》由会员分享,可在线阅读,更多相关《Antlr简介及中文手册.doc(25页珍藏版)》请在咨信网上搜索。
Antlr简介 06通讯软件 06382027 郑毅 本文主要介绍了什么是ANTLR,以及ANTLR的使用,其中ANTLR的使用包括了ANTLR的安装及使用,ANTLR语法文件解析,ANTLR规则(RULE)解析,ANTLR语法实例—SensorSQL,ANTLR Studio及其功能介绍等。 Antlr(ANother Tool for Language Recognition)是一个工具,前身是 PCCTS,它为我们构造自己的识别器(recognizers)、编译器(compiler)和转换器(translators)提供了一个基础。通过定义自己的语言规则,Antlr可以为我们生成相应的语言解析器,这样便可以省却了自己全手工打造的劳苦。 它是这样的一种工具,它可以接受文法语言描述,并能产生识别这些语言的语句的程序。作为翻译程序的一部分,你可以使用简单的操作符和动作来参数化你的文法,使之告诉ANTLR怎样去创建抽象语法树(AST)和怎样产生输出。ANTLR知道怎样去生成识别程序,语言包括Java,C++,C#和不久的Python。 ANTLR知道怎样构建识别程序,这些程序可以对以下三种不同的输入应用文法结构:(i) 字符流, (ii) 记号流,和(iii)两维的树结构。很自然的它们分别与词法分析程序(lexers,以下简称lexer),语言解析程序和树遍历程序向匹配。这个用于定义这些语法的元语言,在所有情况下几乎一样的。 一旦你对ANTLR和类似工具比较顺手,你会开始以一种新的目光来看编程。许多任务强烈需要语言解决方案,而不是采用传统编程语言的做法。比如,这些过程的注解都是用特伦斯标记语言写的。而ANTLR则能来将文本(内含一些额外的东西和转换)转化为HTML,PDF或者其他那些生成程序的文件格式。 最后,ANTLR只是一件工具,仅仅这些。 虽然它能通过将容易理解的乏味部分自动化来帮助你创建软件,但却不能企图让你指定整个编译器。例如,在单个的描述里就不行。那些宣称这类事情非常伟大,可以为发布刊物文章编写惊人的“一揽子解决方案”,却会悲惨失败在实际项目中。 词法分析器(Lexer) 词法分析器又称为Scanner,Lexical analyser和Tokenizer。程序设计语言通常由关键字和严格定义的语法结构组成。编译的最终目的是将程序设计语言的高层指令翻译成物力机器或虚拟机可以执行的指令。此法分析器的工作是分析量化那些本来毫无意义的字符流,将他们翻译成离散的字符组(也就是一个一个的Token)括关键字,标识符,符号(symbols)和操作符供语法分析器使用。 语法分析器(Parser) 编译器又称为Syntactical analyser。在分析字符流的时候,Lexer不关心所生成的单个Token的语法意义及其与上下文之间的关系,而这就是Parser的工作。语法分析器将收到的Tokens组织起来,并转换成为目标语言语法定义所允许的序列。 无论是Lexer还是Parser都是一种识别器,Lexer是字符序列识别器而Parser是Token序列识别器。他们在本质上是类似的东西,而只是在分工上有所不同而已。 ANTLR ANTLR将上述两者结合起来,它允许我们定义识别字符流的词法规则和用于解释Token流的词法分析规则。然后,ANTLR将根据用户提供的语法文件自动生成相应的词法/语法分析器。用户可以利用他们将输入的文本进行编译,并转换成其他形式(如AST—Abstract Syntax Tree,抽象的语法树)。 Antlr使用 安装及使用 到http://www.antlr.org/下载最新版本的ANTLR开发包和源码(例如版本3.01)。将antlr-3.0.1.jar所在目录配置到你的环境变量中,写好语法文件(例如SensorSQL.g),运行命令“java antlr.Tool SensorSQL.g”就可以获得自动生成语法/词法分析器。 ANTLR语法文件解析 下面我们对图中所描述的ANTLR语法文件做一些详细的分析。为了更好的使用ANTLR,你还可以下载ANTLR的Eclipse插件来帮助你完成工作。 1. header域:所有出现在这里的部分,都会出现在由ANTLR编译之后生成的Java文件的最顶部。在本例中你可以将包名和其他信息放到这一区域中,生成的结果如由面对应代码部分所示。 2. 你在这一部分所提供的内容对于文件中的每个语法都是唯一的。这一区域的内容将出现在实际的类定义之前。也就是说,两个import仅属于类CalcParser,而不属于在同一个文件中定义的其他类(如CalcLexer) 3. 这里是语法定义部分,你同样可以将它看成是类定义。 4. 在Option域中,你可以为你的语法提供可选项。例如是否建立缺省的抽象语法树,指定LL(K)中的参数k的值(缺省为1)等等,更详细的参数请参阅ANTLR自带的手册。 5. Token部分用来声明那些在词法分析器中没有被声明的“想象的”token。这些信息通常用在TreeParser中指定“想象”的节点。 6. 这是另一个Action区,ANTLR将会忠实地将这一区域内的信息放置到类的定义当中,相当于类的成员方法,主要为用户提供一种在Parser种定制可扩展方法的途径。 ANTLR规则(RULE)解析 在ANTLR的语法文件中,一个规则的定义是与一个由ANTLR生成的Java源文件相对应的。 1,2,3,4:正如你所看到的那样,我们可以在一个规则定义中作与一个函数等价的所有事情。我们可以为规则指定参数(像上面的int a),制定返回值(int c),甚至抛出一个异常。从右半面我们可以清楚地看到,所有在规则中定义的内容都被忠实而准确的翻译到Java源文件的相应位置。 5:这一可选的部分为我们提供了指定某些可选参数的能力。例如图中所示代表告诉ANTLR在生成代码的时候不要生成缺省的错误处理部分,这部分将由用户自己负责。 7:在异常处理部分,我们可以指定自定义的异常处理方法。像这里就仅仅是打印错误栈信息。 ANTLR语法实例—SensorSQL SensorSQL是一个自定义的简化版SQL语言,它所支持的语法定义这里就不详细列出了,我只是给出查询的示例: 通常,编译一个查询的目的是要把它转化成某种被查询设备可以理解的形式。通常的做法有两种,一种是像在上一节中提到的那样,写好详细的语法规则,在ANTLR生成相应的Java文件之后,就可以直接使用其运行结果。这样的例子有很多,其中最典型的就是对于算数表达式的解析了。对于形如1+2-3*4/5^6这样的表达式,只要写好语法规则,就可以在解析过程中直接得到运算结果:首先ANTLR将其编译成逆波兰结构-- ( - ( + 1 2 ) ( / ( * 3 4 ) ( ^ 5 6 ) ) ) ;在生成语法树的过程中,同步计算表达式的值,即类似于2.3节中看到的表达式计算。结果如下: 不过这样作有一个缺点,就是在很多情况下,你可能并不知道要用什么样的方法来处理。所以当真正要开始写处理代码的时候,就要受限于已有的Parser/Lexer中的代码。一旦要有所修改,就要重新编译语法文件,生成新的Java代码,不胜繁琐。而且,一旦处理过程有误,就要反复调试修改Antlr生成的代。自动生成的代码嘛,结构着实也不怎么样,调试的时候也麻烦。所以如果效率允许的话,就没有必要让Antlr作额外的工作,干脆就专心于做他的语法分析也就是了,其他的工作等到生成语法树之后再怎么遍历或者折腾都可以嘛J。 上图就是刚才演示的SensorSQL语法分析之后产生的结果。在产生这个结果之后,我需要将每一个语法元素翻译成字节序列打包发送给传感器网络。这时候,为了保证Where语句中的优先级,你就可以按照ANTLR文档中关于生成语法树的一章,生成类似于这样的结构,然后只需前序遍历这颗语法树的Where部分就可以达到目的,至于其他部分,顺序遍历一遍就好了。 ANTLR Studio 有了前面的基础之后,我们就可以开始真正的工作了。不过用“记事本或Editplus+命令行”或者干脆写个ANT脚本也不是不可以,但是总觉得在集成化IDE满天飞的时代用这个方式有点过于原始,幸好Placid System 为我们提供了一个Eclipse插件来使我们有机会直接走出原始社会。下载地址为: ANTLR Studio插件的安装 Eclipse下插件的安装自不必多说,要注意的是从Placid System网站上提供的license文件,下载之后它的名字为license.lic.txt,要把它的后缀名.txt去掉,然后放到ECLIPSE_DIR\plugins\AntlrStudio_x.x.x 目录(这里 x.x.x 是版本号, 例如 - 1.1.0)。安装成功之后在Eclipse的工具栏上会出现一个词法分析器的导航按钮: 当右键单点击你的工程时,你会发现控制是否使用ANTLR Studio的开关: 当打开一个文法文件之后,可以看到如下界面: 在右面的大纲窗口,列有所有Parser和Lexer的元素,可以看到Protected Token(例如Number)和其他普通的Token是不一样的;在左面,不同的区域是用不同的颜色块加亮来区分的。 功能介绍 ANTLR Studio在Eclipse Help提供了比较详尽的文档描述,所以这里我只介绍一些1.1.0版本的新功能。 l 完全支持ANTLR3.0.1,并支持将之前的工程自动升级到1.1.0版本。 l Syntax Diagram View,可以方便的查看所输入的语法结构。 l 改进了Debug功能,可以调试比较大的文法文件。而在这之前,如果一个文法文件很大的话,ANTLR Studio就会抛出异常。 l 支持自动的代码补全功能,提供一个ANTLR文档的比较全面的提示信息(如下所示)。 语法图表视图(Syntax Diagram View) 在Window->Show View->Other中选择显示这个视图之后,你就可以使用这个很酷的功能了 利用这个视图,你可以很容易的看到你定义语法的语法结构,例如,我的SELECT语句定义如下 你只需要将光标标放到selectStatement规则的任意位置,就可以在Syntax Diagram View中看到: 于是完整的语法结构清晰的显示在了我们面前。这时你只需要将光标放到脱字符号(^)上面(注:脱字符号用于指明在生成语法树的时候,脱字符号所在的SubRule要作为树或子树的根节点):就会看到: 对应的SubRule被加亮成粉红色,而如果你的光标放到的位置是一个Token的话就会变成淡蓝色,简直太酷了。 增强的Debug功能 想要启动或关闭ANTLR Studio的Debug功能,需要完成以下步骤: l 在工程中启用/取消ANTLR Studio l 右键单击工程,打开“属性”中的ANTLR Studio选项卡。 l 选择/取消'Enable debugging in grammar files' 做完这些后,我们就可以痛快的使用其Debug功能了。与调试其他Java文件一样,我们可以在语法文件的任意位置插入断点: 当程序运行至断点之后,我们同样可以像调试普通应用程序一样使用诸如“跳过”,“继续”等Java应用程序的Debug方式来进行,十分的方便和顺手。 注:以上资料均来于网络,鄙人收集整理。 ANTLR中文手册 06通讯软件 06382027 郑毅 本文主要概括了一些常用的ANTLR的使用方法,其中有Antlr的主要类,Antlr文法文件形式,生成Java类,如何生成Java类,如何执行以及元语言词汇表。 一、Antlr的主要类: Antlr中有主要类有两种(其实还有一种TreeLexer) Lexer:文法分析器类。主要用于把读入的字节流根据规则分段。既把长面条根据你要的尺寸切成一段一段:)并不对其作任何修改。 Parser:解析器类。主要用于处理经过Lexer处理后的各段。一些具体的操作都在这里。 二、Antlr文法文件形式: Antlr文件是*.g形式,即以g为后缀名。 例如:t.g classPextendsParser; startRule :n:NAME {System.out.println("Hithere," n.getText());} ; classLextendsLexer; //one-or-morelettersfollowedbyanewline NAME:(’a’……’z’|’A’……’Z’) NEWLINE ; NEWLINE :’\r’’\n’//DOS |’\n’//UNIX ; 具体成分分析: 1、总体结构 ClassPextendsParser ClassLextendsLexer 两行同JAVA继承一样,P继承Parser类;L继承Lexer类。每个.g文件只能各有一个。 2、Lexer类分析 一般按照类型名:(匹配的具体规则)的形式构成。是分隔字节流的依据。同时可以看到里面可以互相引用。如本例中的类型名NEWLINE出现在NEW的匹配规则中。 3、Parser类分析 一般按照 起始规则名: 规则实例名:类型名或规则名 {Java语句……;} ; 起始规则名:任意。 规则实例名:就象Java中“Strings;”的s一样。规则实例名用于在之后的JAVA语句中调用。 类型名或规则名:可以是在Lexer中定义的类型名,也可以是Parser中定义的规则名。感觉就像是int与Integer的区别。 Java语句:指当满足当前规则时所执行的语句。Antlr会自动嵌入生成的java类中。 三、生成Java类 1、从www.antlr.org上下载antlr-x.x.x.jar 2、配置环境变量:classpath=.;x:\jdk\lib\tools.jar;x:\antlr-x.x.x.jar 3、在t.g所在目录下执行: javaantlr.Toolt.g 会在当前目录下生成如下文件: L.java:Lexer文法分析器java类。 P.java:Parser解析器java类。 PTokenTypes.java:Lexer中定义的类型具体化,供Parser解析器调用。 PTokenTypes.txt:当外部的(如t2.g)要调用当前的类型或规则时要用到本文件。 四、执行 1、编写Main类 importjava.io.*; classMain{ publicstaticvoidmain(String[]args){ try{ Llexer=newL(newDataInputStream(System.in)); Pparser=newP(lexer); parser.startRule(); }catch(Exceptione){ System.err.println("exception:" e); } 2、执行 c:\>javac*.java c:\>javaMain Terence ^Z Hithere,Terence c:\> 元语言词汇表 空格定义 空格,tab符号和换行符号在ANTLR分隔诸如标识符这样的词汇符号时作为分隔符。在这之外,它们是被忽略的。例如,“FirstName LastName”对ANTLR来说两个标记符而不是一个标记符,空格,然后再接着一个标记符。 注释 ANTLR 接受C语言风格的块注释和C++风格的行注释。在语法类和规则中,Java风格的文档注释也是可以接受的,在需要的时候,这些注释可以被传递给生成的输出文件。例如 /**This grammar recognizes simple expressions * @author Terence Parr */ class ExprParser; /**Match a factor */ factor : ... ; 字符集 字符常数像Java中那样被确定。它们包含八进制转义字符集(e.g., '\377'),Unicode字符集(e.g., '\uFF00'),和能被Java识别的常用的字符转义('\b', '\r', '\t', '\n', '\f', '\'', '\\')。在词法分析器规则中,单引号代表一个可以在输入字符流中能得到匹配的的字符。在语法分析器中是不被支持单引号的字符的。 文件结束标志 EOF 标记用语法分析器规则中自动生成: rule : (statement)+ EOF; 你可以在词法分析器规则的动作中检测EOF_CHAR符号: // make sure nothing but newline or // EOF is past the #endif ENDIF { boolean eol=false; } : "#endif" ( ('\n' | '\r') {eol=true;} )? { if (!eol) { if (LA(1)==EOF_CHAR) {error("EOF");} else {error("Invalid chars");} } } ; 当你将文件结束当一个字符来检测时,它实际上并不是一个字符,而是一个条件。 你可以在你的词法分析器语法中覆盖 CharScanner.uponEOF()函数: /** This method is called by YourLexer.nextToken() * when the lexer has * hit EOF condition. EOF is NOT a character. * This method is not called if EOF is reached * during syntactic predicate evaluation or during * evaluation of normal lexical rules, which * presumably would be an IOException. This * traps the "normal" EOF * condition. * * uponEOF() is called after the complete evaluation * of the previous token and only if your parser asks * for another token beyond that last non-EOF token. * * You might want to throw token or char stream * exceptions like: "Heh, premature eof" or a retry * stream exception ("I found the end of this file, * go back to referencing file"). */ public void uponEOF() throws TokenStreamException, CharStreamException { } 文件结束条件是一个位比特。因为Terence 将-1当作一个字符而不是一个整型数。(-1 是 '\uFFFF'). 字符串 字符串常数一个由双引号括起来的一系列字符。在字符串中的字符可以是作为字符也同样合法的转义字符(八进制,Unicode等)。当前,ANTLR实际上不允许Unicode出现在字符串常量中(你不得不用转义符)。这是因为在anglr.g文件中设定charVocabulary选项为ascii. 在词法分析器规则中,字符串被解释成可以在输入流中匹配的一系列字符 (例如., "for" 等于 'f' 'o' 'r'). 在语法分析器规则中,字符串代表一个个标记(tokens),并且每个独立的字符串被分派一个标记类型。然而,ANTLR不会创建一个词法分析器规则来匹配这些字符串。相反,ANTLR将这些字符串输入到一个于词法分析器关联的字符常量表中。ANTLR将针对字符常量表来产生代码检测每个标记中的文本,在手动关掉语法分析器对该标记的处理之前获得一个匹配时,会改变标记的类型。你也可以执行手动检测――自动代码生成可以通过词法分析器选项控制。 你可能想在你的动作中使用这些字符串常量的标记的类型值,例如在错误处理器的同步部分。对于只由字母字符组成的字符串常量来说,这个字符串常量的值将是一个形如LITERAL_xxx的常量值,这里xxx是这个标记的名字。例如,文字“return”将有一个LITERAL_return值与之关联。你也可以用标记节(tokens section)分派一个特定的标号给这个文字。 标记引用 以大写字符开头的标识符称为标记引用。接下来的字符可以是任何字符,数字或下划线。在语法分析器规则中一个标记引用将导致匹配特定的标记。在词法分析器中的标记引用将导致调用一个词法规则来匹配该标记的字符。换句话说,在词法分析器中的标记引用将对当作一个规则引用。 标记定义 在词法分析器中的标记定义由和语法规则中相同的定义。但是当做标记而不是语法规则。例如, class MyParser extends Parser; idList : ( ID )+; // parser rule definition class MyLexer extends Lexer; ID : ( 'a'..'z' )+ ; // token definition 规则引用 以小写字母开头的标识符是为ANTLR的语法规则。接下来的字符可以是任意字母,数字或下划线。词法规则不能引用语法规则。 动作. 在尖括号中的字符序列是语义动作(可能是嵌套的)。在字符串和字符中的尖括号不是动作分隔符。 动作参数 在方括号中的字符序列是动作参数(可能是嵌套的)。在字符串和字符中的方括号不是动作分隔符。在[]中的参数是用被生成的语言的语法定义的,并且用逗号分开。 codeBlock [int scope, String name] // input arguments returns [int x] // return values : ... ; // pass 2 args, get return testcblock {int y;} : y=cblock[1,"John"] ; 许多人喜欢我们用普通的括号来括住参数,但是括号在EBNF中已经被很好的用来定义语法组符号(grammatical grouping symbols)。 符号 下面的表统计了在ANTLR中使用的标点符号和关键字。 符号 描述 (...) 子规则 (...)* 闭包子规则(零和多个) (...)+ 正闭包子规则(一个和多个) (...)? 可选(零个和一个) {...} 语义动作 [...] 规则参数 {...}? 语义谓词 (...)=> 语法谓词 | 可选符 .. 范围符 ~ 非 . 通配符 = 赋值 : 标号符, 规则开始 ; 规则结束 <...> 元素选项 class 语法类 extends 指定语法基类 returns 指定返回类型 options options 节 tokens tokens 节 header header 节 tokens token 定义节 Header 节 一个header节包含了一些将直接被替换到输出的语法分析器中的源码,这些源码将在所有的ANTLR生成的代码之前。这个主要用在C++的输出中,因为C++需要一些元素在引用之前必须被声明。在Java中,这可以用来为最后的语法分析器指定一些包文件。一个header节看起来像下面这样: header { source code in the language generated by ANTLR; } header 节是语法文件的第一个节。根据选择的目标语言的不同,不同类型header节都是可能出现的。看各自的附录。 语法分析器类定义 所有的语法规则必须和一个语法分析器关联。一个语法文件(.g)只包含一个语法分析器类定义(和词法分析器和树遍历器一起)一个语法分析器定义在它的选项(options)和规则定义之前。一个语法文件中的语法分析器定义通常是这个样子: { optional class code preamble } class YourParserClass extends Parser; options tokens { optional action for instance vars/methods } parser rules... 当在面向对象语言中生成代码时,语法分析器类将导致在输出中是一个类,规则都会变成这个类的成员函数。在C中,类将导致生成一个结构,一些名字混淆(name-mangling)算法将用在上面使最终的规则函数是全局唯一的。 可选的类的预定义可以是包含在{}中的任意文本。这个预定义,如果它存在的话,将被直接输出到生成类文件中,并且在类定义之前。 封闭的尖括号不能用来分隔类,因为一个左尖括号在文件顶就很难跟踪与之匹配的右括号在文件的时。相反,一个语法分析器类假定是连续的,知道碰到下一个类的语句。 你可以指定语法分析器超类,它将作为被生成的语法分析器的超类。这个超类必须是完整定义的,在双引号中。它自己必须是antlr.LlkParser的子类。例如 class TinyCParser extends Parser("antlr.debug.ParseTreeDebugParser"); 词法分析器类定义 一个语法分析器类将导致一个知道如何根据输入流的标记来应用语法结构的语法分析器对象。为了执行词法分析,你需要指定一个词法分析器类,它描述了如何将输入流分离成标记流。它的语法类似于语法分析器类: { optional class code preamble } class YourLexerClass extends Lexer; options tokens { optional action for instance vars/methods } lexer rules... 包含在词法分析器中的词法规则在产生的类中变成成员方法。每个语法文件(.g)只包含一个词法分析器。语法分析器和词法分析器可以以任何顺序出现。 可选类的开头是括在{}中的任意文本。这个开头部分,如果它存在,将输出到被生成的类文件中,在类定义的之前。 你可以定义一个词法分析器的超类,它可以被用来作为产生的词法分析器的超类。这个超类将是完整定义的(fully-qualified),在双引号中,它自身是antlr.CharScanner子类。 树分析器定义 一个树分析器像语法分析器,不同的是它处理二维的由节点组成的抽象语法树,而不是处理由标记组成的流。树分析器必须唯一指定给语法分析器,除非规则定义中包含特殊形式致使它递归下降到树中。同样,一个特定的语法文件(.g)中仅仅包含一个树分析器。 { optional class code preamble } class YourTreeParserClass extends TreeParser; options tokens { optional action for instance vars/methods } tree parser rules... 你可以定义一个树分析器的超类,它可以被用来作为产生的树解析器的超类。这个超类将是完整定义的(fully-qualified),在双引号中,它自身是antlr.TreeParser子类 注:以上资料均来于网络,鄙人收集整理。 计算器及文法文件 06通讯软件 06382027 郑毅 本文主要介绍了利用ANTLR达到计算器需求以及利用ANTLR生成C++描述的分析程序。 一.利用ANTLR达到计算器需求 1.运算符:+,-,×,÷,(,) 2.支持整型和浮点型 测试样例 1.1+ 2 * 3 + 5 - 4/2 2.(1 + 2) * 3 + 5 - 4 / (2+2) 3.(1.2*2.5)+8/(4-3)*2.7 下面就让我们动手完成一个计算器,:) 先搭个框架。文件名是calc.g options { language = “Cpp”; } class CalcParser extends Parser; class CalcLexer extends Lexer; 这些就是基本框架了。 options里设置language为”Cpp”,表示要生成c++代码。 CalcParser是我们的计算器的语法解析类,继承ANTLR里的Parser类。 同理,CalcLexer是词法分析类,继承ANTLR里的Lexer类。 接着定义计算器的词法规则。 首先是运算符。 PLUS : ‘+’; SUB : ‘-’ ; MUL : ‘*’ ; DIV : ‘/’ ; LPAREN : ‘(’ ; RPAREN : ‘)’ ; 接着是操作数。 NUM : (’0′..’9′)+ { $setType(INT); } (’.’ (’0′..’9′)+ { $setType(REAL); } )? ; (注: $setType是ANTLR内置函数,用来设置token类型。就是当匹配到(’0′..’9′)*后,设置token类型为INT,当发现后面跟着小数点和数字后,重新设置token类型为REAL。) WS : (’ ‘ | ‘\t’ | ‘\n’ | ‘\r’)+ { $setType(ANTLR_USE_NAMESPACE(antlr)Token::SKIP); } ; statement : mexpr ( (PLUS | SUB) mexpr )* ; mexpr : expr ( (MUL | DIV) expr )* ; expr : INT | REAL | LPAREN statement RPAREN ; 一个计算器的语法程序就写好了。让我们来生成c++代码,实际测试一下. $java -cp /usr/share/java/antlr.jar antlr.Tool calc.g ANTLR Parser Generator Version 2.7.6 (20060528) 1989-2005 $ls calc.g CalcParser.cpp CalcParserTokenTypes.txt CalcLexer.cpp CalcParser.hpp CalcLexer.hpp CalcParserTokenTypes.hpp $ 我们可以看到,生成了6个文件。 CalcTest.cpp: #include “CalcLexer.hpp” #include “CalcParser.hpp” #include using namespace std; using namespace antlr; int main() { try { CalcLexer lexer(cin); CalcParser parser(lexer); parser.statement(); } catch (exception &e) { cout << e.what() << endl; } } 编译之: $g++ -o Calc CalcTest.cpp CalcParser.cpp CalcLexer.cpp -lantlr 测试用例: $ ./Calc 1 + 2 * 3 + 5 - 4/2 $ ./Calc (1 + 2) * 3 + 5 - 4 / (2+2) $ ./Calc (1.2*2.5)+8/(4-3)*2.7 $ 二.利用ANTLR生成C++描述的分析程序 文法文件 文法就是语言识别的规则。它是ANTLR生成程序的依据。文法文件是ANTLR的核心,是程序员和ANTLR进行交流的接口。 文法文件的编写基本是面向被解决的问题的。程序员只需要集中精力思考解决问题的逻辑,而不是羁绊于某种程序设计语言的实现细节,因此降低了出现错误的可能性。 文法文件的语法简介(转自ANTLR中文手册) 本文只是简单地介绍一个文法文件的语法,具体内容可以参阅ANTLR的相关文档。 文法文件一般包括header块、options块、文法分析器类(parser)及规则定义、词法分扫描器类(lexer)及token定义。其中最为重要的是规则和token的定义。 规则的定义形式和编译理论中的扩展巴科斯范式(EBNF)极为相似,包括规则名、规则体、一个用作结束标志的分号和异常处理部分(可省略)。例如如下的规则就描述了C语言中的赋值语句的语法: assignment_stat: id '=' expr ';' ; 其意义是:一条赋值语句是由一个id、一个等号、一个表达式和一个分号顺序组成的。 Token的定义方法与规则类似。例如如下的token定义就表示一个十进制的整数: NUM: ('1'..'9')('0'..'9')* ; 其意义是:数字(NUM)的第一字符是‘1’到‘9’中的一个字符,后面是0个或多个‘0’到‘9’之间的字符。 需要注意的一点是:规则的名字必须是小写字母开始,而token的名字则必须是大写字母开始。 设定ANTLR生成的语言(转自ANTLR中文手册) ANTLR有很多选项,可以通过在文法文件中的options块中进行设置,其中包括ANTLR最终生- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Antlr 简介 中文 手册
咨信网温馨提示:
1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前自行私信或留言给上传者【xrp****65】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时私信或留言给本站上传会员【xrp****65】,需本站解决可联系【 微信客服】、【 QQ客服】,若有其他问题请点击或扫码反馈【 服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【 版权申诉】”(推荐),意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4008-655-100;投诉/维权电话:4009-655-100。
1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前自行私信或留言给上传者【xrp****65】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时私信或留言给本站上传会员【xrp****65】,需本站解决可联系【 微信客服】、【 QQ客服】,若有其他问题请点击或扫码反馈【 服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【 版权申诉】”(推荐),意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4008-655-100;投诉/维权电话:4009-655-100。
关于本文