C语言的lex和yacc工具说明

合集下载

Lex和Yacc从入门到精通(PDF)

Lex和Yacc从入门到精通(PDF)

Lex和Yacc从入门到精通熊春雷Abstract在开发程序的过程中经常会遇到文本解析的问题,例如:解析C语言源程序,编写 脚本引擎等等,解决这种文本解析的方法有很多,一种方法就是自己手动用C或者 C++直接编写解析程序,这对于简单格式的文本信息来说,不会是什么问题,但是 对于稍微复杂一点的文本信息的解析来说,手工编写解析器将会是一件漫长痛苦 而容易出错的事情。

本系列文档就是专门用来由浅入深的介绍两个有名的Unix工 具Lex和Yacc,并会一步一步的详细解释如何用这两个工具来实现我们想要的任何 功能的解析程序,为了方便理解和应用,我会在该系列的文章中尽可能的采用具 体可行的实例来加以阐释,而且这种实例都是尽可能的和具体的系统平台无关的 ,因此我采用命令行程序作为我们的解析程序的最终结果。

1、环境配置篇开发Lex和Yacc程序最需要的程序就是lex和yacc了,如果你是Unix或者Linux系统,则 系统自带了这两个工具,无需安装,不过值得说明的是GNU/Linux下面的Lex是flex, 而Yacc则是bison。

另外需要的就是一个C/C++语言编译器,由于我们采用的是GNU的 lex和yacc,所以,理所当然的我们就使用GNU的编译器了,如果是Unix或者Linux系统 ,那么编译器应该已经安装了。

在这里我重点讨论的是Windows系统环境下的Lex和 Yacc程序的开发,至于为什么选择Windows系统作为开发平台,则是为了尽可能的让初 学者容易入门。

1.1.必备工具言归正传,首先列举Windows平台下面Lex和Yacc开发环境所需要安装的程序:1.Lex(flex.exe)和Yacc(bison.exe)环境2.C/C++编译器1.2.flex和bison值得说明的是,flex.exe和bison.exe是UnxUtils包中的文件,已经将许多 Unix/Linux平台的程序都移植到了Windows平台,可以直接到UnxUtils网站下载,下载解压缩之后在系统的PATH环境变量中增加UnxUtils所有的exe文件所在的目录,使 得DOS命令行可以直接搜索到flex.exe和bison.exe,除此之外还需要从网络上下载 bison需要的bison.simple和bison.hairy两个文件,并且还要分别设置环境变量 BISON_HAIRY指向bison.hairy,BISON_SIMPLE指向bison.simple。

编译原理-实验二-FLEX词法分析器

编译原理-实验二-FLEX词法分析器

编译原理-实验⼆-FLEX词法分析器FLEX词法分析器⼀、Lex和Yacc介绍Lex 是⼀种⽣成扫描器的⼯具。

扫描器是⼀种识别⽂本中的词汇模式的程序。

⼀种匹配的常规表达式可能会包含相关的动作。

这⼀动作可能还包括返回⼀个标记。

当 Lex 接收到⽂件或⽂本形式的输⼊时,它试图将⽂本与常规表达式进⾏匹配。

它⼀次读⼊⼀个输⼊字符,直到找到⼀个匹配的模式。

如果能够找到⼀个匹配的模式,Lex 就执⾏相关的动作(可能包括返回⼀个标记)。

另⼀⽅⾯,如果没有可以匹配的常规表达式,将会停⽌进⼀步的处理,Lex 将显⽰⼀个错误消息。

Yacc代表 Yet Another Compiler Compiler 。

Yacc 的 GNU 版叫做 Bison。

它是⼀种⼯具,将任何⼀种编程语⾔的所有语法翻译成针对此种语⾔的 Yacc 语法解析器。

(下载下载flex和bison。

⽹址分别是/packages/flex.htm和/packages/bison.htm。

)⼆、配置环境(win7)①下载flex和bison并安装到D:\GnuWin32(尽量是根⽬录)②由于我们使⽤的flex和bison都是GNU的⼯具,所以为了⽅便,采⽤的C/C++编译器也采⽤GNU的编译器GCC,当然我们需要的也是Windows版本的GCC了。

所以提前准备好VC 6.0③检验是否可以进⾏lex⽂件编译1.新建⽂本⽂件,更改名称为lex.l,敲⼊下⾯代码%{int yywrap(void);%}%%%%int yywrap(void){return 1;}2.新建⽂本⽂件,更改名称为yacc.y,敲⼊下⾯代码%{void yyerror(const char *s);%}%%program:;%%void yyerror(const char *s){}int main(){yyparse();}我们暂且不讨论上⾯代码的意思。

打开控制台,进⼊到刚才所建⽴⽂件(lex.l,yacc.y)所在的⽂件夹。

lex和Yacc详解

lex和Yacc详解

Lex和Y acc工具介绍――编译原理的实用工具1.词法分词器生成工具lexLex的主要功能是生成一个词法分析器(scanner)的C源码。

描述词法分析器的文件,经过lex编译后,生成一个lex.yy.c的文件,然后由C编译器编译生成一个词法分析器。

词法分析器,简单来说,其任务就是将输入的各种符号,转化成相应的标识符(token),转化后的标识符很容被后续阶段处理。

过程如错误!未找到引用源。

图1现在这个lex 文件可以用来生成一个统计行数、字符个数和单词个数的工具。

规则段是由正则表达式和相应的动作组成的。

p 1 {action 1}p 2 {action 2}……p n {action n }值得注意的是,lex 依次尝试每一个规则,尽可能地匹配最长的输入流。

如果有一些内容根可以看出lex的确按照最长的规则匹配。

程序段部分放一些扫描器的其它模块,比如一些动作执行时需要的模块。

也可以在另一个程序文件中编写,最后再链接到一起。

生成C代码后,需用C的编译器编译。

连接时需要指定链接库。

gcc的连接参数为 -ll。

2.正则表达式正则表达式可以描述有穷状态自动机(Finite Automata)接受的语言,也就是定义一个可以接受的串的集合。

转义字符(也称操作符):" \ [ ] ^ - ? . * + | ( ) $ / { } % < >这些符号有特殊含义,不能用来匹配自身。

如果需要匹配的话,可以通过引号(’’)或者转义符号(\)来指示。

比如C”++”C\+\+都可以匹配C++。

非转义字符:所有除了转义字符之外的字符都是非转义字符。

一个非转义字符可以匹配自身。

比如integer匹配文本中出现的integer。

通配符:通配符就是”.”(dot),可以匹配任何一个字符。

字符集:用一对[]指定的字符构成一个字符集。

比如[abc]表示一个字符集,可以匹配a、b、c中的任意一个字符。

使用–可以指定范围。

lex工具实例

lex工具实例

翻译规则部分(续)


为避免二义性,在Ri中 若需出现空格、回车或 制表符,则应用‘\s’, ‘\n’,‘\t’表示。 每个代码段Actioni可 引用已定义的常量、全 局变量和外部变量,也 可以调用在辅助函数部 分定义的函数。
注意:Actioni中的C
程序语句多于一条时, 必须用花括号{ }将 它们括起来,否 则,LEX将会报错
词法分析程序的使用



用户可通过调用函数yylex()使用词法分析程序。每调 用yylex()函数一次,yylex()将从输入流中识别一个单词, 并返回一个整型值(被识别出的单词之内部码)。 所谓单词的内部码是指词法分析程序在识别出某一类 单词时所返回的整型数值(也称为类别码),它由用 户自行定义其取值。 例如,用户可定义标识符Id的内部码为300,实型数 RealNo的内部码为450等等。一般说来,用户自定义的 单词类别码应大于256,而小于256的内部码值可用于 字符单词的类别码,用其ASCII码值来表示。如单词 '+'的内部码可定义为‘+’的ASCII码值43。
LEX的命令格式及选项
格式:lex [-ctvn -V -Q[y|n]] [files] 选项: -c 指明动作为C语句(缺省设置). -t 输出到stdout 而不是 lex.yy.c(缺省设置); -v 提供一个两行的统计概述 -n 不输出-v的概述 -V 在stderr上输出lex的版本信息. -Q[y|n] y:在输出文件lex.yy.c上打印版本信息. n:不打印(缺省设置). 若files为多个文件,则被视为一个,若files为空,则使用stdin.
1.声明(declaration)
LEX的声明又可以分两个

Lex和Yacc工具使用方法

Lex和Yacc工具使用方法

编译器的自动生成工具LEX和YACC的使用方法Lex自动地表示把输入串词法结构的正规式及相应的动作转换成一个宿主语言的程序,即词法分析程序,它有一个固定的名字yyler,在这里yyler是一个C语言的程序。

Yylex将识别出输入串中的词形,并且在识别出某词形时完成指定的动作。

看一个简单的例子:写一个lex源程序,将输入串中的小写字母转换成相应的大定字母。

程序如下:%%[a-z]printf(“%c”.yytext[0]+'A'-'a');上述程序中的第一行%%是一个分界符,表示识别规则的开始。

第二行就是识别规则。

左边是识别小写字母的正规式。

右边就是识别出小写字母时采取的动作:将小写字母转换成相应的大写字母。

Lex的工作原理是将源程序中的正规式转换成相应的确定有限自动机,而相应的动作则插入到yylox中适当的地方,控制流由该确定有限自动机的解释器掌握,不同的源程序,这个解释器是相同的。

1.2 lex源程序的格式lex源程序的一般格式是:{辅助定义的部分}%%{识别规则部分}%%{用户子程序部分}其中用花括号起来的各部分都不是必须有的。

当没有“用户子程序部分”时,第二个%%也可以省去。

第一个%%是必须的,因为它标志着识别规则部分的开始,最短的合法的lex源程序是:%%它的作用是将输入串照原样抄到输出文件中。

识别规则部分是Lex源程序的核心。

它是一张表,左边一列是正规式,右边一列是相应的动作。

下面是一条典型的识别规则:integer printf("found keywcrd INT");这条规则的意思是在输入串中寻找词形“integer”,每当与之匹配成功时,就打印出“foundkeyword INT”这句话。

注意在识别规则中,正规式与动作之间必须用空格分隔开。

动作部分如果只是一个简单的C表达式,则可以写在正规式右边同一行中,如果动作需要占两行以上,则须用花括号括起来,否则会出错。

LEX和YACC的使用(例子)

LEX和YACC的使用(例子)

LEX和YACC的使⽤(例⼦)1、简单C语⾔的词法分析程序;%{#include<stdio.h>#include<stdlib.h>#include<ctype.h>#include<string.h>%}digit [0-9]letter [A-Za-z]other_char [!-@\[-~]id ({letter}|[_])({letter}|{digit}|[_])*string {({letter}|{digit}|{other_char})+}int_num {digit}+%%[ |\t|\n]+ "auto"|"double"|"int"|"struct"|"break"|"else"|"long"|"switch"|"case"|"enum"|"register"|"typedef"|"char"|"extern"|"return"|"union"|"const"|"float"|"short"|"unsigned"|"continue"|"for"|"signed"|"void"|"default"|"go \"([!-~])*\" {printf("CONST_string,%s\n",yytext);}-?{int_num}[.]{int_num}?([E][+|-]?{int_num})? {printf("CONST_real,%s\n",yytext);}"0x"?{int_num} {printf("CONST_int,%s\n",yytext);}","|";"|"("|")"|"{"|"}"|"["|"]"|"->"|"."|"!"|"~"|"++"|"--"|"*"|"&"|"sizeof"|"/"|"%"|"+"|"-"|">"|"<"|">="|"<="|"=="|"!="|"&"|"^"|"|"|"&"|"||"|"+="|"-="|"*="|"/="|"%="|">>="|"<<="|"&="|"^="|"|="|"=" {printf("%s,NULL\n",yytext);}{id} {printf("ID,%s\n",yytext);}{digit}({letter})+ {printf("error1:%s\n",yytext);}%%#include <ctype.h>Upper(char *s,int l){int i;for(i=0;i<l;i++){s[i]=toupper(s[i]);}}yywrap(){return 1;}注意:要得到输出信息,需要⾃⾏添加main函数,lex默认的main函数没有输出的。

YACC

yacc(Yet Another Compiler Compiler),是一个经典的生成语法分析器的工具。

是Unix/Linux上一个用来生成编译器的编译器(编译器代码生成器)。

yacc生成的编译器主要是用C语言写成的语法解析器(Parser),需要与词法解析器Lex一起使用,再把两部份产生出来的C程序一并编译。

yacc本来只在Unix系统上才有,但现时已普遍移植往Windows 及其他平台。

分析程序生成器(parser generator)是一个指定某个格式中的一种语言的语法作为它的输入,并为该种语言产生分析过程以作为它的输出的程序。

在历史上,分析程序生成器被称作编译-编译程序( compiler- compiler ),这是由于按照规律可将所有的编译步骤作为包含在分析程序中的动作来执行。

现在的观点是将分析程序仅考虑为编译处理的一个部分,所以这个术语也就有些过时了。

合并 LALR(1) 分析算法是一种常用的分析生成器,它被称作 Yacc( yet another compiler- compiler )。

给出 Yacc 的概貌来,将使用Yacc为 TINY 语言开发一个分析程序。

作为 Yacc 对说明文件中的 %token NUMBER 声明的对应。

Yacc 坚持定义所有的符号记号本身,而不是从别的地方引入一个定义。

但是却有可能通过在记号声明中的记号名之后书写一个值来指定将赋给记号的数字值。

yacc的输入是巴科斯范式(BNF)表达的语法规则以及语法规约的处理代码,Yacc输出的是基于表驱动的编译器,包含输入的语法规约的处理代码部分。

yacc是开发编译器的一个有用的工具,采用LALR(1)语法分析方法。

Yacc最初由AT&T的Steven C. Johnson为Unix操作系统开发,后来一些兼容的程序如Berkeley Yacc,GNU bison,MKS yacc和Abraxas yacc陆续出现。

编译原理 lex和yacc的综合设计 python

编译原理lex和yacc的综合设计python
1、Lex和Yacc是一种强大的词法分析和语法分析技术,它们常用于编译器的开发和编写编译器前端。

它们分别可以分析和解释输入字符流,并产生相应的输出。

Lex是一个词法分析器,它可以将输入字符流分解为令牌(即识别的节点),这些令牌可以用于编写解释器或编译器的前端。

Yacc则是一种用来构建语法分析器的工具,它可以识别输入的令牌序列,并生成相应的程序。

2、编译原理是编译器的最小系统,它涉及源程序的分析和分解,目标程序的生成和优化,以及中间代码的翻译。

Lex和Yacc则是用来处理字符流和语法检查的两个有力工具,在处理中间代码生成和优化方面非常有用,是编译器的核心部分。

3、Lex和Yacc的综合设计一般需要借助某种语言将可执行模块链接起来,最常用的技术是使用C,C是一种高性能语言,可以让开发者实现快速迭代,也可以利用其标准库实现代码复用,因此是完成Lex和Yacc综合设计的最佳语言。

4、Python是一种脚本语言,不适合用于编写Lex和Yacc综合设计,因为Python 并不专业,不能满足低级程序设计的需求,处理过程中往往性能不佳。

LEX和YACC入门

用 %% 符号隔开。第一部分和最后一个部分是宿主语言代 码。中间是由一系列规则构成,
LEX 将这些规则翻译为词法分析器。每一个规则依次包含一 个正则表达式以及该正则表达式得到匹配时要运行的一些代 码。
任何没有得到匹配的文本则简单地拷贝到标准输出。
2020/5/13
6
三、LEX程序设计
LEX正规表达式(1)
expression: value '+' value { System.out.println("Matched a '+' expression.\n"); }
2020/5/13
23
四、YACC程序设计
类似于 LEX, YACC 也有 一套变量和函数可供用户 来进行功能扩展。
YYSTYPE 定义了用来将 值从 lexer 拷贝到解析器 或者 YACC 的 yylval ( 另一个 YACC 变量)的 类型。默认的类型是 int 。 由于字符串可以从
的值。
2020/5/13
26
四、LEX与YACC结合
2020/5/13
27
public static void main(String args[]) {
int n = 1;
mylexer lexer = new mylexer();
if (lexer.yycreate(null)) {
n = lexer.yylex();
}
System.out.println("word count = "+lexer.wordCount);
两个百分号标记指出了 LEX程序中这一段的结束和三段中第二段 的开始。
10

Lex使用指南

Lex使用指南Lex是由美国Bell实验室等人用C语言开发的一种词法分析器自动生成工具,它提供一种供开发者编写词法规则(正规式等)的语言(Lex语言)以及这种语言的翻译器(这种翻译器将Lex语言编写的规则翻译成为C语言程序)。

Lex是linux下的工具,本实验使用的编译工具是cygwin(cygwin在windows下模拟一个linux环境)下的flex,它与lex的使用方法基本相同,只有很少的差别。

一、Lex的基本原理和使用方法Lex的基本工作原理为:由正规式生成NFA,将NFA变换成DFA,DFA经化简后,模拟生成词法分析器。

其中正规式由开发者使用Lex语言编写,其余部分由Lex翻译器完成.翻译器将Lex源程序翻译成一个名为的C语言源文件,此文件含有两部分内容:一部分是根据正规式所构造的DFA状态转移表,另一部分是用来驱动该表的总控程序yylex()。

当主程序需要从输入字符流中识别一个记号时,只需要调用一次yylex()就可以了。

为了使用Lex所生成的词法分析器,我们需要将程序用C编译器进行编译,并将相关支持库函数连入目标代码。

Lex的使用步骤可如下图所示:生成词法分析器的过程:使用所生成的词法分析器的过程:二、lex源程序的写法:Lex源程序必须按照Lex语言的规范来写,其核心是一组词法规则(正规式)。

一般而言,一个Lex源程序分为三部分,三部分之间以符号%%分隔。

`[第一部分:定义段]%%第二部分:词法规则段[%%第三部分:辅助函数段]其中,第一部分及第三部分和第三部分之上的%%都可以省略(即上述方括号括起的部分可以省略)。

以%开头的符号和关键字,或者是词法规则段的各个规则一般顶着行首来写,前面没有空格。

Lex源程序中可以有注释,注释由/*和*/括起,但是请注意,注释的行首需要有前导空白。

1. 第一部分定义段的写法:定义段可以分为两部分:第一部分以符号%{和%}包裹,里面为以C语法写的一些定义和声明:例如,文件包含,宏定义,常数定义,全局变量及外部变量定义,函数声明等。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C语言的lex和yacc工具说明Lex工具-------Lex工具是一种词法分析程序生成器,它可以根据词法规则说明书的要求来生成单词识别程序,由该程序识别出输入文本中的各个单词。

1、lex程序的结构-定义部分-规则部分-用户子程序部分其中规则部分是必须的,定义和用户子程序部分是任选的。

(1) 定义部分定义部分起始于"%{"符号,终止于"%}"符号,其间可以是包括include语句、声明语句在内的C语句。

%{#include "stdio.h"#include "y.tab.h"extern int lineno;%}(2) 规则部分规则部分起始于"%%"符号,终止于"%%"符号,其间则是词法规则。

词法规则由模式和动作两部分组成。

模式部分可以由任意的正则表达式组成,动作部分是由C语言语句组成,这些语句用来对所匹配的模式进行相应处理。

需要注意的是,lex将识别出来的单词存放在yytext[]字符数据中,因此该数组的内容就代表了所识别出来的单词的内容。

%%[\t] {;}[0-9]+\.?|[0-9]*\.[0-9]+{ sscanf(yytext,"%1f", &yylval.val);return NUMBER; }\n { lineno++;return '\n'; }. { return yytex+[0]; }%%(3) 用户子程序部分用户子程序部分可以包含用C语言编写的子程序,而这些子程序可以用在前面的动作中,这样就可以达到简化编程的目的。

下面是带有用户子程序的lex程序片段。

"/*" skipcmnts();. /* rest of rules */%%skipcmnts(){for ( ; ; ){while (input()!='*');if(input()!='/')unput(yytext[yylen-1]);else return;}2、lex工具的使用方法首先编写一个lex程序vi lex.l%{#include "stdio.h"%}%%[\n] ;[0-9]+ printf("Interger: %s \n",yytext);[0-9]*\.[0-9]+ printf("Float: %s\n",yytext);[a-zA-Z][a-zA-Z0-9]* printf("Word:%s\n",yytext);. printf("Other symbol:%c\n",yytext[0]);%%然后使用lex将lex.l转换成C语言程序$lex lex.l使用上述命令产生的C语言程序为lex.yy.c然后使用C编译程序将lex.yy.c编译成可执行程序regn $cc -c lex.yy.c$cc lex.yy.o -ll -o regn下面可以使用regn来识别单词$vi testfilex=355y=113p=x/y# ./regn < testfileWord:xOther symbol:=Interger: 355Word:yOther symbol:=Interger: 113Word:pOther symbol:=Word:xOther symbol:/Word:y#yacc工具--------yacc工具是一种语法分析程序生成器,它可以将有关某种语言的语法说明书转换成相应的语法分析程序,由该程序完成对相应语言中语句的语法分析工作。

1、yacc程序结构在使用yacc工具前,必须首先编写yacc程序,因为有关语法分析程序是根据yacc程序生成的。

yacc程序实际上是有关语法规则的说明书,它也是由定义部分、规则部分和子程序部分组成的。

yacc程序的定义部分类似于lex程序的定义部分,只是在其后可带有yacc声明,其中包括词法单词、语法变量、优先级和结合性信息。

yacc程序的规则部分由语法规则和相应的动作组成,子程序部分可以包括在前面规则部分用到的子程序定义。

接下来是main主程序,它调用yyparse子程序来对输入进行语法分析,而yyparse反复地调用yylex子程序来获得输入单词,在语法出错时可通过yyerror子程序来处理。

2、yacc工具的使用方法实例:我们将yacc程序分成片段,把这些片段组合在一起就是yacc程序。

我们要使用的语法规则是一个有关四则运算的语法规则,可用BNF范式描述list: expr \nlist expr \nexpr :NUMBERexpr + exprexpr - exprexpr * exprexpr / expr(expr)其含义是list是一个表达式序列,每个后面带有一个新行。

表达式是一个数值,或是由运算符连起来的两个表达式,以及用圆括号括起来的表达式。

下面是有关上述语法规则的yacc程序片段。

$vi hoc.y%{#define YYSTYPE double%}%token NUMBER%left '+' '-'%left '*' '/'%%list:| list '\n'| list expr '\n' { printf("\t%. 8g\n",$2);};expr : NUMBER {$$=$1;}| expr '+' expr {$$ = $1 + $3; }| expr '-' expr {$$ = $1 - $3; }| expr '*' expr {$$ = $1 * $3; }| expr '/' expr {$$ = $1 / $3; }| '('expr')' {$$ = $2; }%%上述yacc程序片段实际上是它的定义部分和规则部分。

在yacc声明部分,%token NUMBER表明了NUMBER是一个单词符号,%left则表明了运算符号的左结合性,并且'*'和'/'和优先级比'+'和'-'的优先级高。

在yacc程序的规则部分,备用规则是用'|'隔开的,规则中的动作实际上是C语句序列,其中$n(即$1,$2等)是用来引用规则中的第几个成份,而$$则代表了整个规则的返回值。

下面的yacc程序片段是main主程序#include <stdio.h>#include <ctype.h>char *progname;int lineno=1;main(argc,argv)int argc;char *argv[];{ progname = argv[0];yyparse();}main主程序调用yyparse子程序来处理来处理输入,而yyparse又是通过yylex子程序来获得输入单词并通过yyerror子程序来报告出错信息。

下面是有关这两个子程序的yacc程序片段yylex(){ int c;while ((c=getchar()) == ' ' || c=='\t') ;if (c==EOF)return 0;if (c=='.'||isdigit(c)){ungetc(c,stdin);scanf("%lf", &yylval);return NUMBER;}if(c=='\n')lineno++;return c;}yyerror(s)char *s;{ warning (s,(char *)0);}warning(s,t)char *s,*t;{ fprintf(stderr,"%s:%s",progname,s);if(t)fprintf(stderr,"%s",t);fprintf(stderr," near line %d\n",lineno);}这样就完成了整个yacc程序接下来就使用yacc将hoc.y转换成C语言程序$yacc hoc.y使用上述命令产生的C语言程序为y.tab.c,这时可以使用C编译程序将它编译成可执行程序hoc.$cc y.tab.c -o hoc下面是使用hoc的例子# ./hoc4*3*224(1+2)*(3+4)211/20.5355/1332.6691729-3-4./hoc:Syntax error near line 5上述结果显示中,分别表明了计算结果,最后一次计算出错的原因是由于在规则定义中未来定义单目减运算符号。

相关文档
最新文档