`
jackyhongvip
  • 浏览: 159684 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ANTLR笔记2 - 简单语法说明

 
阅读更多

ANTLR的语法文件使用扩展巴科斯范式EBNF描述,记得编译原理的用起来非常简单,需要进一步了解的是怎么构造自己的recognizer和translator。很多的语法不需要从头写,一方面很多语言标准中基本都使用EBNF描述,另一方面ANTLR网站http://www.antlr.org/grammar/list上有大量写好的语法文件,可以参考使用。
我已经忘得一干二净,从头大致了解一下。

巴科斯范式扩展符号 EBNF
() : 产生式组合
?  : 产生式出现0或1次
*  : 0或多次
+  : 1或多次
.   : 任意一个字符
~  : 不出现后面的字符
..  : 字符范围
可以参考http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html

例子1,整数定义:
integer : (HEX_PREFIX | OCTAL_PREFIX)? DIGITS; //可以有一个16进制或8进制前缀,没有则为10进制定义
HEX_PREFIX: '0x'; //16进制前缀
OCTAL_PREFIX: '0o'; //8进制前缀
DIGITS: '1'..'9' '0'..'9'*; //第一个字符必须为1-9,后面可以是任意多个0-9字符

例子2,多行注释符号/*和*/的定义:
ML_COMMENT : '/*' ( options {greedy=false;} : . )* '*/' ;
/*开头,*/结束,(.)*表示中间可以有任意多个字符,options {greedy=false;}是一个谓词选项,告诉分析器不要采用贪婪模式,即匹配到随后出现的第一个*/就结束,而不是试图去匹配输入字符流中的最后一个*/。

左递归、右递归 left/right recursion
如果一个产生式在最左开始位置包含它自己,叫左递归,例如exp: A | exp ',' A。而exp: A ',' exp | A则是右递归。用实际例子来看。
1. 右递归
例如实现一个表达式: +8结果为9;++8结果为10;+++8结果为11,以此类推。右递归语法为:
expr: PLUS expr | INT;
INT: '1'..'9' '0'..'9'*;
PLUS: '+';
用ANTLR笔记1中C#示例的方法来运行这个例子的语法文件内容如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->left returns [int value] : e=expr { $value = $e.value; };
expr returns [int value] :
    PLUS e
=expr { $value=$e.value+1; }
    | INT { 
$value=int.Parse( $INT.text ); };
INT: '
1'..'9' '0'..'9'*;
PLUS: '
+';

有个理解上容易产生歧义的地方,即expr应当解析成expr: (PLUS expr) | INT;还是expr: PLUS (expr | INT);?应当是前面这种方式。
2. 左递归
例如实现表达式: 8+结果为9;8++结果为10;8+++结果为11,以此类推。左递归语法为:
expr: expr | INT PLUS;
INT: '1'..'9' '0'..'9'*;
PLUS: '+';
ANTLR不支持左递归,上面的语法在生成时会报错: error(210):  The following sets of rules are mutually left-recursive [expr]。
将这个语法改为下面这样,就不是左递归了。
expr: INT PLUS*;
INT: '1'..'9' '0'..'9'*;
PLUS: '+';

零散的概念
语法多义性: 语法设计最值得关注的问题。第一点是人的思维对语法描述理解的歧义,与语法解释器的实际结果不一致,例如上面提到的expr的问题。另外就是语法描述本身逻辑上存在多义性,即对同样的输入可以解释成多种结果,它们都符合语法描述的规则。

lexer: 词法分析器,从输入字符流解析出词汇序列(tokens)。
parser: 语法解析器,对词汇进行语法分析,生成语法树(抽象语法树AST)。
EBNF的语法不区分词法分析和语法分析,对应的只有终结符、非终结符,终结符描述输入,非终结符描述输入所表达的树结构。ANTLR使用词法分析器识别终结符,使用语法分析器分析非终结符(生成的分析器代码文件有两个,一个是词法分析器***Lexer,一个是语法分析器***Parser),并要求词法规则全部以大写开始,语法规则全部以小写开始。对每一个语法规则,最终都必须以词法规则结束,否则是一个无效语法,生成时会报错。

ANTLR生成的分析器代码中,语法规则都会有一个同名的方法,而词法规则的名称则跟语法文件给出的不一样。如果需要使用这些词法规则,可取的方法之一是定义一个语法规则与之对应;另外就是定义一个符号表,例如ANTLR笔记1中示例1里面的tokens{...}。定义符号表的优点是会优先匹配符号表,例如一些关键字等,可以避免他们被其它规则匹配上。
关于规则的定义顺序,语法文件中先出现的规则具有优先匹配的作用。

ANTLR笔记1中示例1的简单说明
1. grammar SimpleCalc;,定义语法名称。语法文件(.g文件)名称必须与这里指定的名称一致。默认情况生成的语法分析器类名为"语法名称"+Parser,词法分析器类名为"语法名称"+Lexer。
2. options {...},定义全局配置参数,设置ANTLR生成过程中的一些控制选项,示例中指定目标语言为C#。
3. tokens {...},定义全局的符号表。
4.
@members {...},这里面给出的代码将放入到生成的语法分析器类中,作为分析器类的成员属性、方法等。
   示例中为分析器添加了一个Main方法,省得再格外写一个测试类。
   Main方法先从命令行读取输入字符,将输入字符传给生成的词法分析器
SimpleCalcLexer,得到词汇序列CommonTokenStream。接下来使用生成的语法分析器SimpleCalcParser对词汇序列进行分析,在生成语法树的过程中直接由expr()方法返回计算结果。
5. 语法规则。
   把语法规则中的{...}、[...]等相关ANTLR的Action去掉就是EBNF。
   ANTLR生成的语法解析器代码中,对应每个语法规则都会生成一个方法,这个方法完成对应语法规则的分析逻辑。
{...}、[...]等就是我们自己的recognizer、translator需要的一些额外控制(Action),分析匹配的逻辑由ANTLR完成,我们添加的这些控制就是对匹配到的结果怎样进行处理,是生成一个语法树,再由其它程序对语法树进行翻译,还是直接结合ANTLR的分析过程进行翻译转换或计算处理等,由我们进行控制。示例中是直接进行计算求值。
   returns [...]告诉ANTLR生成的方法需要返回什么内容,[int value]表示返回值类型为int,名字叫做value,就是声明了一个变量,用它来返回。在方法体里面,我们通过{...}中的内容进行求值运算,并把结果设置给value。{...}我们可以看作是一个宏,或者是一个模板,在里面我们可以使用ANTLR在代码生成时内置的一些变量/对象,它们以$开始(象StringTemplate语法,但不需要对应的$进行闭合),这些变量在代码生成过程中ANTLR为我们设置好。其它的代码保持不变,放入到方法的相应位置上。
6. 词法规则。
   $channel = HIDDEN; }。默认情况下ANTLR在词法分析器和语法分析器之间使用两个通道通讯,一个default和一个hidden。语法分析器监听default通道接收词汇序列,所以如果将某个词汇发送到hidden通道,这个词汇就会被语法分析器忽略掉。示例中将回车换行等空白字符都过滤掉,不进行语法分析。
  
fragment: 对词法规则有效(我没有看到对语法规则有作用),它在生成的语法树上不会有对应的节点,即可以这样理解,它是我们在语法中定义的一个宏,可以被其它语法规则调用,但它不会成为最终语法树上的节点。

分享到:
评论

相关推荐

    antlr4-short-course

    ANTLR 4简明教程是一本介绍ANTLR 4使用方法的书籍,内容基于最新版ANTLR 4的语法编写,作者在阅读官方参考书时整理了自己的读书笔记,并在此基础上增加了新的内容。这本书以开源形式编写,源码托管在GitHub上,方便...

    antlr笔记

    2. **生成解析器**:ANTLR将语法文件转换为解析器代码,这个解析器可以是LL(1)、LL(k)、LR(1)或LALR(1)类型的解析器。ANTLR支持自定义属性传播和语法动作,使得解析过程中可以进行复杂的操作。 3. **词法分析**:...

    The Definitive ANTLR4Reference 学习笔记

    ANTLR 4是ANTLR系列的最新版本,它提供了对现代编程语言语法模式的全面支持,并具有强大的错误恢复机制。 学习ANTLR 4的参考手册时,首先需要了解的是语言、语法、解析树、词法单元和解析器的基本概念。语言由一...

    antlr4读书笔记七八章

    ### ANTLR4读书笔记七八章详解 #### 第七章:从特定于应用程序的代码解耦语法 在学习了如何使用ANTLR定义语言语法后,我们了解到语法本身虽然能够验证一个输入句子是否符合语言规范,但对于实际开发语言应用程序来...

    The+Definitive+ANTLR+4+Reference 学习笔记word

    此外,ANTLR4还引入了如语法动作、树遍历和访问、自定义属性语义等高级概念,这些都将在学习笔记中详细阐述。通过深入学习和实践,你可以掌握创建自定义解析器和编译器的关键技能,从而实现对特定语言或格式的解析和...

    An Introduction To ANTLR

    例如,Terence Parr本人就使用ANTLR开发了一个名为TML(Terence's Markup Language)的简单标记语言,用于撰写课程笔记和其他文档。TML被设计为易于编写,通过ANTLR转换成HTML或PDF格式,从而简化了文档创作的过程。...

    CXF webservice初学笔记

    在 CXF 中,ANTLR 可能被用于解析和生成 XML 相关的语法。 5. **Commons Collections** (commons-collections-3.2.1.jar):Apache Commons Collections 是一个增强版的 Java 集合框架,提供了一系列实用的集合类和...

    语法分析器 编译课 计算机学习

    在描述中提到的“该语法分析器在给出一个具体的语法后能自动生成一个C文件的语法器”,这通常指的是使用诸如Yacc(Yet Another Compiler-Compiler)或者ANTLR等工具来实现。这些工具接受一种形式化的文法描述(如...

    很棒

    v4-为ANTLR v4编写的语法; 期望语法没有动作。 ASL 小米NoteBook Pro Hackintosh 艾达 带有蒸汽朋克设置的天空中的镜子 阿格达 -Cedille,一种基于依赖Lambda消除演算的依赖类型编程语言 苹果脚本 -Emacs扩展,...

    awesome-stars-by-sandeep

    Jupyter笔记本(2) 物镜-C(2) 其他(21) 巨蟒(10) Ruby(3) Rust(5) Scala(1) 贝壳(6) 迅捷(4) 打字稿(38) Vue(1) ANTLR 姓名 描述 作者 星星 1个 语法-v4 为ANTLR v4编写的文法;...

    TigerWorks:佐治亚理工学院 CS4240 的 Tiger 编译器

    2. `antlr` - ANTLR 生成的解析器和词法分析器的代码。 3. `tests` - 测试用例,用于验证编译器的正确性。 4. `docs` - 项目文档,包括设计决策、用户指南和开发者笔记。 5. `Makefile` - 构建脚本,用于编译和测试...

    C++、MFC源代码parser_src

    1. 说明.htm:这是一个HTML文件,通常用于提供项目的详细说明、使用指南或者开发者笔记。 2. 代码中国.txt:可能包含与项目相关的代码片段、注释或者其他信息,可能是作者为了记录或分享代码而创建的文本文件。 3. ...

    编译原理 词法分析器.zip

    - **ANTLR**:一种强大的解析器生成器,支持多种语言,可以生成词法分析器、语法分析器和抽象语法树。 深入学习词法分析器涉及语言学、计算机科学和软件工程等多个领域的知识,有助于提升对编译器和解释器工作的...

    dsfffwefgsgvfgc

    在学习编译原理的过程中,我们通常会接触到各种工具和方法,比如LR、LL、LL(k)、LR(k)、LALR(1)等解析算法,以及Yacc、ANTLR、Flex等用于构建编译器的工具。此外,对正则表达式、上下文无关文法和上下文敏感文法的...

    游戏未命名

    2. **命令行解析**:如果游戏有内置的命令行界面,Yacc可以帮助解析用户输入的命令,进行相应的操作,如改变游戏设置、加载存档等。 3. **游戏数据结构解析**:游戏中的各种配置文件或数据文件可能采用了自定义格式...

    编译器-2021-spring

    实践项目可能包括编写简单的编译器或解释器,理解编译器的每个阶段,并应用编译器构造工具,如ANTLR或Yacc。 通过"compilers-2021-spring-main"这个文件名,我们可以推测这可能是课程的主要材料,可能包含了课程...

    独家! 中国科技大学 陈意云 编译原理全套!课堂ppt,历年考试真题,课程实验讲稿

    实验可能包括使用工具如ANTLR或Yacc来构建词法分析器和语法分析器,或者编写简单的编译器前端,处理简单的程序语言。这样的实践有助于培养学生的编程能力和问题解决能力。 压缩包内的文档文件可能是陈意云教授的...

    Hibernate新手上路

    2. `antlr-2.7.6rc1.jar`:提供了语法解析和生成器,用于处理Hibernate的HQL(Hibernate Query Language)和其他配置文件。 3. `cglib-2.1.3.jar`:生成字节码库,Hibernate使用它来动态创建实体类的代理,以便实现...

    编译原理答案

    在实际应用中,编译原理的工具如ANTLR、Yacc和Flex等被广泛使用,它们可以帮助开发者自动生成词法分析器和语法解析器。理解这些工具的工作原理和使用方法,可以提升开发效率,降低软件开发的复杂度。 总结而言,...

Global site tag (gtag.js) - Google Analytics