LEMON的特殊声明符的应用场景及用途总结

特殊申明符号备注
%token_type   ,%type  :
在LEMON中必须专门使用这两个申明符来指定终结符或者非终结符的类型 。所有的 终结符都必须具有唯一的一种数据类型, 意味着Parse()函数的第三个参数(记号的值)必须具有某种特定的统一的数据类型,通常我们 指针指向具有某种特定的统一的数据类型的记号的值来传递第三个参数。若未指定,则默认为void  】如,%token_type  {Token*} ,每个非终结符可以有自身的数据类型,因此可以量身定做, 最典型的非终结符数据类型是一个指向语法分析树树根的指针 ,因此它具有最大的包容度,可以把所有非终结符的信息都包含进来,如 %type expr {Expr*}
终结符由 %token_type指定!
%default_type为避免繁琐的为众多非终结符分别指定数据类型,可以使用%default_type为非终结符指定默认的统一的数据类型。这样占据最多数量的某一类非终结符的数据类型就可以用%default_type来统一指定。
%destructor用于指定摧毁非终结符并且释放由它占用内存的那部分代码块。
%token_destructor用于摧毁指定的终结符
%default_destructor许多非终结符可以共用一个析构器,借用此申明符可以指定一种通用的统一的非终结符析构器作为默认析构器。
%include指定 C/C++代码 ,Lemon会原封不动的拷贝这部分包含的代码到语法分析器的前部。可以多次出现,但是会覆盖掉前一个include中的内容,可以有效的利用它达到需要的效果 。产生式中需要用到的头文件,必须在%include中包含。
%code指定 C/C++代码 ,它指定的代码,附加在语法分析器的后部,它一般包含了词法分析器,输入输出部分,以及调用分析器的main函数。这是为了方便YACC使用者的使用。
%left左结合性 ,每一个出现在%left之右但是在黑句点“."之前的终结符,全部都予同样的左结合性和同样的优先级。如果其后又使用%left制定了新的终结符,那么后者指定的终结符具有更高的优先级。
%right为了避免规约栈中的待规约字符超过栈的限制,尽量不使用右结合性来,除非万不得已。
%nonassoc用来声明不应该在某一个产生始终同时存在的非终结符,如,EQ,NE,GT(>),GE
,LT,LE .我们不应该在一个if语句中出现这样的情景(if(a==b==c){……})
%start_symbol用此指定语法的开始符号,若没有指定,以语法文件的第一个非终结符作为开始符号
%extra_argument指定进行语法分析时送进的第四个参数,即Parse()函数要求的第四个参数,如果语法文件中由这样的声明:
%extra_argument{MyStruct * pAbc}
那么,Parse()函数所需要的第四个参数pAbc就有了Mystruct* 这个数据类型,而每一次调用了Parse()函数,各个C语言动作过程都可以读写以pAbc命名的这个变量。

特别注意 :这是一个输入输出变量,程序通过它与解析器进行通信,如果指定了这个特殊声明符,就与Parse()函数的第四个参数建立了关系 ,在语法文件中对这个参量的修改 ,外部程序都可以通过Parse()函数的第四个参数了解到 。这个参量指定的类型以及这个参量的初始化,内存空间分配都需要程序要自己把握 。(刚学习的时候这个地方花了我不少时间啊 )
%name通常所有的Lemon自动生成的函数都是以"Parse"这5个字符开头,为避免冲突,可使用%name来指定另外的前缀 。若使用 %name abcc  。那么前缀都变成了abcc ,连那个解析函数Parse()也会变成abcc()
%token_prefixLemon总用#defines 定义某个整数作为终结符"身份证"唯一号码,如果用%token_prefix指定某几个字符作为终结符前缀的话,则当LEMON用#defines定义时,它还会在每个终结符之前加上这个前缀。
%stack_sizeLEMON内定的堆栈大小时100个元素。当有需要时修改这个值。
%stack_overflow可以指定一个C语言代码块,当内部的语法分析栈溢出时,就调用这段代码来执行指定的动作。一般溢出时由于存在右递归或者是右结合的操作符,这时可以把右递归改成左递归或者是左结合的操作运算符,并尽量保持短的语法规约。且最好使用左递归的语法规则,而不是右递归的。
%syntax_error指定一段C代码。当语法出错时,调用。
%parse_accept当语法分析器正确无误的处理整个输入文件后,可到达接受状态。完全规约成功时,调用此部分。
%parse_failure语法分析器错误时,会尝试着从错误中恢复过来,当无效以致无法继续时,才会调用%parse_failure指定的C语言动作代码。这部分一般来说是给出一个教准确的出错信息。
%ifdef-%endif 和%ifndef-%endif作用类似于C语言的条件编译#ifdef-#endif,由他们包含的内容的取舍与命令行中"-D"选项指定的宏名有关
()、[]、{}、::=、.LEMON中,()括起来的字符串必须紧接着某个终结符或者非终结符之后,表示别名,也代表终结符或者非中介符的符号值,这个字符串,在产生式后部的C语言执行代码段中作为变量而引用。[]括起来的部分一般是伪终结符,作用是为某个产生式指定非常规的优先级,使用时,必须将有他括起来的字符串放置在相应的产生式的黑句点后。并把它所具有的优先级和结合性指定到该产生式右部从后倒数所碰到的第一个终结符身上。{}括起来的是C代码段。::=可看成是节点与子节点的联系符,它左边的非终结符是节点,右边的终结符和/或非终结符是子节点。"." 黑句点表示产生式的结束 ,有时也表示一个特殊申明符指定的内容的结束。
%fallback ID  ACTION AFTER
 ACTION等 如果不是被解析为他本来的值的时候,将会被解析为ID 。


编译语法文件时提示的很多冲突都可以通过 %left ,%right 以及 %nonassoc 来指定优先级和结合方式而解决 ,相信你是可以写出零冲突的高效率的语法文件的 。
优先级 ,越靠后的优先级越高 ,同一级的优先级是相同的 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值