当前位置:文档之家› 语法分析程序

语法分析程序

语法分析程序
语法分析程序

HUNAN UNIVERSITY 编译原理实验报告

题目:语法分析器的实现

学生姓名:杨玉茹

学生学号:201508010325

专业班级:计科1503

上课老师:杨晓波

目录

一、实验目的 ............................................................ 错误!未定义书签。

二、实验任务 (2)

三、实验内容 (2)

四、系统设计 (2)

五、实验测试 (12)

六、实验体会 (13)

附录(源代码及注释) (14)

一、实验目的

(一)学习已有编译器的经典语法分析源程序。

(二)通过本次实验,加深对语法分析的理解,学会编制语法分析器。

二、实验任务

(一)阅读已有编译器的经典语法分析源程序,并测试语法分析器的输出。

(二)用C或JA V A语言编写一门语言的语法分析器。

三、实验内容

(一)学习经典的语法分析器(2学时)

(1)选择一个编译器,如:TINY或PL/0,其它编译器也可(需自备源代码)。

(2)通过将定义语言的语法规则的BNF文法改写成EBNF文法,以利于递归下降分析算法。

(3)阅读语法分析源程序,加上你自己的理解。尤其要求对相关函数与重要变量的作用与功能进行稍微详细的描述。若能加上学习心得则更好。TINY语言请参考《编译原理及实践》第3.7节;PL/0语言请参考相关实现文档。对TINY语言要特别注意抽象语法树的定义与应用。对PL/0语言要特别注意各种符号表的处理。

(4)测试语法分析器。对TINY语言要求输出测试程序的字符形式的抽象语法树。(手工或编程)画出图形形式的抽象语法树。对PL/0语言要求给出测试程序的各种符号表的内容。

TINY语言:

测试用例一:sample.tny。

测试用例二:用TINY语言自编一个程序计算任意两个正整数的最大公约数与最大公倍数。

PL/0语言:

测试用例一~三:test.pls,test2.pls,a1.pls。

(二)实现一门语言的语法分析器(6学时)

(1)语言确定:C-语言,其定义在《编译原理及实践》附录A中。也可选择其它语言,不过要有该语言的详细定义(可仿照C-语言)。一旦选定,不能更改,因为要在以后继续实现编译器的其它部分。鼓励自己定义一门语言。

(2)完成C-语言的BNF文法到EBNF文法的转换。通过这一转换,消除左递归,提取左公因子,将文法改写为LL(1)文法,以适用于自顶向下的语法分析。规划需要将哪些非终结符写成递归下降函数。(3)为每一个将要写成递归下降函数的非终结符,如:变量声明、函数声明、语句序列、语句、表达式等,定义其抽象语法子树的形式结构,然后定义C-语言的语法树的数据结构。

(4)仿照前面学习的语法分析器,编写选定语言的语法分析器。

(5)准备2~3个测试用例,测试并解释程序的运行结果。

四、系统设计

(1)实验设计思路分析:

思路:

主函数里面的执行步骤:(由于我所使用的绘图软件不能导出图片,因此只能通过截屏)

(2)代码分析

A.声明产生式Pronode:包括三部分,产生式左边、产生式的推导符号、产生式右边

B.每次声明一个产生式以后需要对产生式进行初始化;

C.输入一个含有产生式的文件txt以后,需要对文件进行读取,因此这里使用了ReadPro 函数进行读取;读取的方式主要是运用库函数fsanf以输入流的方式进行读取;分三段进行读取,产生式的左边、终结推介符号、右边;

D.打印txt文件里面含有的产生式PrintPro;

E.对产生式里面的终结符号和非终结符号分别用SetUnTerminate和SetTerminate进行存储到UnTerminate和Terminate两个数组当中去;用bool数flag对表里面的内容进行标记,如果已经含有了,就不需要再进行存储了;如果没有标记过,就加入表中去;

F.获得产生式的First集合以及Follow集合;

First集合的求解方法:○1如果右边的第一个字符是一个终结符号,那么直接加入到First 集合当中去;○2如果右边的第一个字符是非终结符号,若对于产生式右边的一切非终结符,均可推出ε,则将ε加进FIRST集,○3将产生式右边能推出空字符的非终结符的Frist集中不含ε的终结符加入到该非终结符的Fisrt集;○4产生式右边不能推出空字符的非终结符的

Frist集加入到该非终结符的Fisrt集;

变量说明:

bool IsNull(char c):非终结符能否产生空字符

bool IsTerminate(char c):判断是否为终结符号

void AddChar(char chArray[],char c):将非终结符的所有first值加入First集void AddCharToChar(char chArray[],char otherArray[]):将非终结符的所有first集加入First集

void AddCharToChar(char chArray[],char otherArray[]):将非终结符的所有first集加入First集

void AddFollow(char follow[],char c);将非终结符的所有follow值加入Follow集

Follow集合的求解方法:○1将$放进Follow(S)集合当中去,其中S是开始符号;

○2如果存在一个产生式A->aCB,那么FOLLOW(B)中除了$之外的所有符号都在FOOLOW(B)当中了;

○3如果存在一个产生式A->aB,或者存在产生式A->aCB且FIRST(B)包含空,那么FOLLOW (A)中的所有的符号都在FOLLOW(B)中;

G.根据给出的First集合和Follow集合选择出对应的输入的符号对应的产生式SetSelect;步骤:

○1扫描每一个产生式,求出Select集合

○2如果产生式的右边第一字符为终结符,则将其加入select集

○3如果产生式的右边字符为ε,则应将左边字符的follow集加入select集

产生式右边的第一个字符为非终结符,则逐个分析:若α=X1X2 … Xnα′,其中Xi∈VN , 1≤i≤n;若ε∈FIRST(X1),则将FIRST(X2)中的一切非ε的终结符加进FIRST(α), FIRST(α)则应加入select集;以此类推

○4处理像E->ABaβ的产生式的情况,若α=X1X2 … Xnα′,其中Xi∈VN , 1≤i≤n;若对

于一切1≤i≤n,ε∈FIRST(Xi),则将follow(α)加入select集合;

相关代码(由于代码太长了,只截取了一部分的代码):

H.构造分析表SetSheet,根据我们已经求出来的FIRST集合和FOLLOW集合,构造出预测分析表:

I.输入我所需要分析的字符串void InputSym();

J.万事具备只欠东风,此时所有的事情已经准备好了,那么就只需要一一的进行分析; void Scan()函数就将字符串的分析过程体现出来了,当然这个分析过程包含了以下几个重要的部分:

存储符号的栈:包括栈底和栈顶,以及栈的大小

存储剩余符号的队列:队列里面包含了两个结构,一个是数据,一个是指向下一个数据的指针;

预测分析表:也就是我们刚刚构造出来的分析表SetSheet;

每一步操作所运用到的产生式PrintSheet(int row,int col):

F分析的过程:

○1将#压入栈中,Push(SymStack,'#');

○2开始符号入栈,Push(SymStack,UnTerminate[0]);

○3读入第一个符号:a = GetSym(Remain);

○4查看是否和输入符号的第一个符号对应,如果没有的话,就继续在栈中进行左递推;○5如果对应了就将此符号出队列,然后再进行左递推;

五、实验测试

我的pro.txt文件里面的产生式为:

打印出的产生式与我的产生式是一样的:

得出的分析表:

对i*i进行预测分析时执行的步骤:

六、实验心得

a)实验问题:

1)程序读不到我的pro.txt文件

刚开始的时候,我写了一个读取txt文件里面的产生式的文件,可以每

次我输入文件名以后,程序也不报任何的错误或者信息,也没有显示

不能读取,我检查了半天我的程序,最后发现是我最后在txt文件里面

末尾少写了一个#。

b)实验心得:

由于有了之前几次实验的基础,所以这次在理解题意的时候变得相对的简单一点了,不过这次实验明显比前几次都难,涉及到的步骤程序太多了,因此思绪很容易乱。不过由于之前我已经把LL的方法透彻的理解过了,所以相对要好一些,过程中遇到了不少的麻烦,所以部分的代码

借鉴了网上的。LL(1)分析器是自顶向下的一个最重要的分析,所以这是我们这学期该重点掌握的内容,所以做实验的过程也加强了我对这个算法的理解。

七、附录(源代码及注释)

代码附在文件夹里面

HUNAN UNIVERSITY 编译原理实验报告

题目:LL(1)分析

学生姓名:杨玉茹

学生学号:201508010325

专业班级:计科1503

上课老师:杨晓波、陈浩

目录

一、实验目的 ............................................................ 错误!未定义书签。

二、实验任务 (2)

三、实验内容 (2)

四、系统设计 (2)

五、实验测试 (12)

六、实验体会 (13)

附录(源代码及注释) (14)

二、实验目的

学习和掌握LL(1)文法的判定和LL(1)分析方法。

二、实验任务

(1)存储文法的LL(1)分析表;

(2)根据LL(1)分析表判断文法是否LL(1)文法;

(3)实现LL(1)分析过程。

三、实验内容

(1)确定LL(1)分析表的文件存储格式。

要求为3个以上测试文法准备好相应LL(1)分析表的存储文件。

(2)根据LL(1)分析表判断文法是否LL(1)文法。

看每个表项是否最多只有一条候选式,如是该文法是LL(1)文法。

(3)实现LL(1)分析过程。

当(2)判断出该文法是LL(1)文法时,要求给出3个以上输入串的LL(1)分析过程,并判断输入串是否该文法的合法句子。

四、系统设计

(1)实验设计思路分析:

思路:

主函数里面的执行步骤:(由于我所使用的绘图软件不能导出图片,因此只能通过截屏)

●实验的主线是

求First集合和Follow集合->构造分析表->判断文法是否是LL文法->实现LL(1)的分析过程

(2)前期准备工作(变量的声明、结构的构造)

A.声明产生式Pronode:包括三部分,产生式左边、产生式的推导符号、产生式右边

B.每次声明一个产生式以后需要对产生式进行初始化;

C.输入一个含有产生式的文件txt以后,需要对文件进行读取,因此这里使用了ReadPro

语法分析程序的要求

语法分析程序大作业 一、作业目的和要求 通过设计、编制、调试一个典型的语法分析程序(任选有代表性的语法分析方法,如LL(1)、递归下降分析法、LR、算符优先分析法)等,作为编制语法分析程序的依据,对词法分析器所提供的单词序列进行语法检测和结构分析,实现并进一步掌握常用的语法分析方法。 二、作业内容 选择对各种常见高级程序设计语言都较为通用的语法结构作为分析对象(例如表达式、if、while、for等等),给出其文法规则描述(注意,文法规则的描述要符合所选分析方法的要求,比如用LL(1)分析法,文法必须是LL(1)文法),设计并实现一个完整的语法分析程序。 输入:源程序以文件的形式输入。 输出:对于输入的源程序,如果输入源程序是给定文法定义的合法程序,则输出”success”,如果不是,即输入源程序有错误,则输出“Error”,并且尽可能指出出错位置和原因。 三、作业要求 1、说明语法分析的源语言是什么? 能分析的语法成分有哪些(比如if、while、表达式、switch等等)。 给出每个语法规则的文法描述。(可以自定义语法成分,设计合理的语法规则。) 2、说明选择的语法分析方法是哪种?描述总体设计思路和主要的流程图。 3、编程实现,程序中编写的各种函数,需要给出注释,说明函数的作用。 四、结果分析 1、输入正确的源程序截图: 输出结果截图: 2、输入错误的源程序截图: 输出结果截图: 3、总结(自己的心得体会、你编写的语法分析程序的优缺点) 作业分工 上交内容:将以下文件打包压缩,压缩包命名:班级学号姓名_语法分析大作业 学号姓名以组长名字命名即可 1、本报告 2、语法分析程序代码 3、编译生成可执行程序 4、用于测试的源程序代码文件。

语法分析程序报告

xx理工大学 《编译原理》 题目语法分析程序 姓名: 学号: 班级:

一、实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。 二、实验要求 利用C语言编制递归下降分析程序,并对简单语言进行语法分析。 2.1 待分析的简单语言的语法 用扩充的BNF表示如下: ⑴<程序>::=begin<语句串>end ⑵<语句串>::=<语句>{;<语句>} ⑶<语句>::=<赋值语句> ⑷<赋值语句>::=ID:=<表达式> ⑸<表达式>::=<项>{+<项> | -<项>} ⑹<项>::=<因子>{*<因子> | /<因子> ⑺<因子>::=ID | NUM | (<表达式>) 2.2 实验要求说明 输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。 例如: 输入begin a:=9; x:=2*3; b:=a+x end # 输出success 输入x:=a+b*c end # 输出error 2.3 语法分析程序的酸法思想 ⑴主程序示意图如图2-1所示。 图2-1 语法分析主程序示意图 ⑵递归下降分析程序示意图如图2-2所示。 ⑶语句串分析过程示意图如图2-3所示。

图2-2 递归下降分析程序示意图 图2-3 语句串分析示意图 ⑷statement 语句分析程序流程如图2-4、2-5、2-6、2-7所示。 图2-4 statement 语句分析函数示意图 图2-5 expression 表达式分析函数示意图

图2-7 factor分析过程示意图三、语法分析程序的C语言程序源代码 #include "stdio.h" #include "string.h" char prog[100],token[8],ch; char *rwtab[6]={"begin","if","then","while","do","end"}; int syn,p,m,n,sum; int kk; factor(); expression(); yucu(); term(); statement(); lrparser(); scaner(); main() { p=kk=0; printf("\nGrade:05 Class:03 Name:Qiyubing Number:200507096 \n"); printf("\n----Please input the string end with '#':-------- \n"); do

编译原理(语法分析程序设计)

一、实验内容和目的 1. 已知待分析的C语言子集的语法,用EBNF表示如下: (1)<程序>→main()<语句块> (2)<语句块>→“{” <语句串>“}” (3)<语句串>→<语句>{;<语句>} ; (4)<语句>→<赋值语句>|<条件语句>|<循环语句> (5)<赋值语句>→ID=<表达式> (6)<条件语句>→if(条件)<语句块> (7)<循环语句>→while(<条件>)<语句块> (8)<条件>→<表达式><关系运算符><表达式> (9)<表达式>→<项>{+<项>}|<项>{-<项>} (10)<项>→<因子>{*<因子>}|<因子>{/<因子>} (11)<因子>→ID|NUM|(<表达式>) (12)<关系运算符>→<|<=|>|>=|==|!= 2. 实验目的、要求实现的功能 实验目的:编制一个语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析。 实验要求:在上机(一)词法分析的基础上,采用递归子程序法或其他适合的语法分析方法,实现其语法分析程序。要求编译后能检查出语法错误。 3. 将实验方法改写为适合预测分析法的文法如下: (1) <程序>→main()<语句块> (2)<语句块>→{ <语句串>} (3)<语句串>→<语句>; <语句串> (3_1) <语句串>→ε (4)<语句>→<赋值语句> (5)<语句>→<条件语句> (6) <语句>→<循环语句> (7)<赋值语句>→ID=<表达式> (8)<条件语句>→if(<条件>)<语句块> (9)<循环语句>→while(<条件>)<语句块> (10)<条件>→<表达式><关系运算符><表达式> (11)<表达式>→<项><表达式`> (11_1)<表达式`>→+<项><表达式`> (11_2)<表达式`>→-<项><表达式`> (11_3)<表达式`>→ε (12) <项>→<因子><项`> (12_1) <项`>→*<因子><项`> (12_2)<项`>→/<因子><项`> (12_3)<项`>→ε (13) <因子>→ID (14) <因子>→NUM (15) <因子>→(<表达式>) (16) <关系运算符>→< (17) <关系运算符>→<=

语法分析程序实验报告及代码

LL(1)语法分析实验报告 一、实验题目 LL(1)语法分析 二、实验目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,检查语法错误,进一步掌握常用的语法分析方法。 三、实验内容 构造LL(1)语法分析程序,任意输入一个文法符号串,并判断它是否为文法的一个句子。程序要求为该文法构造预测分析表,并按照预测分析算法对输入串进行语法分析,判别程序是否符合已知的语法规则,如果不符合则输出错误信息。 消除递归前的文法消除递归和提取公因子后的等价文法 S →S ∨ a T | a T | ∨ a T S→aTS’ |vaTS’ T →∧ a T | ∧a S’→vaTS’ |ε T→∧ a T’ T’→∧ aT’ |ε 根据已建立的分析表,对下列输入串:a∧ a∧ a进行语法分析,判断其是否符合文法。 四、实验要求 1.根据已由的文法规则建立LL(1)分析表; 2.输出分析过程。 请输入待分析的字符串: a∧ a∧ a 符号栈输入串所用产生式

#S a∧ a∧ a# #S’Ta a∧ a∧ a# S→aTS’ #S’T ∧ a∧ a# # S’T’a∧∧ a∧ a# T→∧ a T’ # S’T’a a∧ a# # S’T’∧ a# # S’T’a∧∧ a# T’→∧ aT’ # S’ T’a a# # S’ T’# # S’ # T’→ε # # S’→ε 五、程序思路 模块结构: 1、定义部分:定义常量、变量、数据结构。 2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等); 3、运行程序:让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则; 4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简单的错误提示。 六、程序源代码 /* 程序名称: LL(1)文法分析程序 */ /* S->S>aT|aT|>aT */ /* T->

语义分析程序的设计与实现

语义分析程序的设计与实现 班号:2008211316姓名:张荣学号:08211627序号:26 实验日期:2010-11-23 一:实验内容: (2) 二:实验要求: (2) 三:实验方法: (2) ◆由LEX建立YACC的词法分析程序 (2) ◆yacc原理介绍 (3) ◆词法分析 (4) ◆解析器如何工作 (5) ◆Yacc环境 (6) ◆常用代码 (7) 第四:YACC内部名称: (7) 第五:运行结果(源代码见附录) (8) 第六:实验总结 (9) 第七:附录 (10) 附录一:yacc程序,加注释 (10) 附录二:词法分析器的工作原理 (16)

一:实验内容: 编写语法分析程序,实现对算术表达式的语法分析,要求所分析的算术表达式由如下的文法产生。 ◆E->E+T|E-T|T ◆T->T*F|T/F|F ◆F->id|(E)|num 二:实验要求: 在对表达式进行分析的同时,输出所采用的产生式。 可以采用多种方法 ◆编写递归调用程序,实现自顶向下的分析。 ◆编写LL(1)语法分析程序,要求: ◇编程实现算法4.2,为给定的文法自动构造预测分析表 ◇编程实现算法4.1,构造LL(1)预测分析程序, ◆编写语法分析程序,实现自底向上的分析,要求: ◇构造识别所有活前缀的DFA ◇构造LR分析表 ◇编程实现算法4.3,构造LR分析程序 ◆利用yacc自动生成语法分析程序,调用LEX自动生成的词法分析器程序 三:实验方法: ◆由LEX建立YACC的词法分析程序 由LEX产生的词法分析程序可用于YACC,LEX编译程序根据LEX

源程序产生词法分析程序yylex(),这个名字就是YACC所需要的词法分析程序的名字。如果YACC要调用LEX产生的词法分析程序,则在YACC源程序的第三部分用语句#include“lex.yy.c”代替函数yylex()的定义,这一yylex()就可以访问YACC中记号的名字,因为LEX的输出时候YACC输出文件的一部分,所有,每个LEX的动作都返回YACC 知道的终结符。 在UNIX的环境下,如果LEX源程序在first.l中,YACC的源程序在second.y中,可以使用以下命令得到所需要的分析程序。 Lex first.l Yacc second.y cc-o yaccdemo y.tab.c lex.yy.c ◆yacc原理介绍 Yacc 是用可移植的C 语言写成的。接受的规定类别是非常一般性的: 带有去歧义规则的LALR(1) 文法。 Yacc 提供了一个通用工具来在计算机程序的输入上施加结构。Yacc 用户准备输入处理的规定;它包括描述输入结构的规则,在识别了这些规则的时候调用的代码,和做基本输入的一个低层例程。Yacc 接着生成一个函数来控制输入处理。这个函数叫做解析器(parser),它调用用户提供的低层输入例程(词法分析器(analyzer))来从输入流中选取基本项目(叫做记号(token))。依据叫做文法规则的输入结构规则来组织这些记号;在识别了这些规则中的某一个的时候,接着调用为这个规则提供的叫做动作的用户代码;动作有能力返回值并

编译原理实验报告(词法分析器-语法分析器).doc

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的:1,词法分析器能够识别简单语言的单词符号 2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。 三、实验要求:给出一个简单语言单词符号的种别编码词法分析器 四、实验原理: 1、词法分析程序的算法思想 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 2、程序流程图 (1 (2)扫描子程序

3

五、实验内容: 1、实验分析 编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。 2 实验词法分析器源程序: #include #include #include int i,j,k; char c,s,a[20],token[20]={'0'}; int letter(char s){ if((s>=97)&&(s<=122)) return(1); else return(0); } int digit(char s){ if((s>=48)&&(s<=57)) return(1); else return(0); } void get(){ s=a[i]; i=i+1; } void retract(){ i=i-1; } int lookup(char token[20]){ if(strcmp(token,"while")==0) return(1); else if(strcmp(token,"if")==0) return(2); else if(strcmp(token,"else")==0) return(3); else if(strcmp(token,"switch")==0) return(4); else if(strcmp(token,"case")==0) return(5); else return(0); } void main() { printf("please input string :\n"); i=0; do{i=i+1; scanf("%c",&a[i]);

实验5 LL(1)语法分析程序的设计与实现(C语言)

实验五LL(1)文法识别程序设计 一、实验目的 通过LL(1)文法识别程序的设计理解自顶向下的语法分析思想。 二、实验重难点 FIRST集合、FOLLOW集合、SELECT集合元素的求解,预测分析表的构造。 三、实验内容与要求 实验内容: 1.阅读并理解实验案例中LL(1)文法判别的程序实现; 2.参考实验案例,完成简单的LL(1)文法判别程序设计。 四、实验学时 4课时 五、实验设备与环境 C语言编译环境 六、实验案例 1.实验要求 参考教材93页预测分析方法,94页图5.11 预测分析程序框图,编写表达式文法的识别程序。要求对输入的LL(1)文法字符串,程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。 表达式文法为: E→E+T|T T→T*F|F F→i|(E) 2.参考代码

为了更好的理解代码,建议将图5.11做如下标注:

/* 程序名称:LL(1)语法分析程序*/ /* E->E+T|T */ /* T->T*F|F */ /* F->(E)|i */ /*目的: 对输入LL(1)文法字符串,本程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。 /********************************************/ /* 程序相关说明*/ /* A=E' B=T' */ /* 预测分析表中列号、行号*/ /* 0=E 1=E' 2=T 3=T' 4=F */ /* 0=i 1=+ 2=* 3=( 4=) 5=# */ /************************************/ #include"iostream" #include "stdio.h" #include "malloc.h" #include "conio.h" /*定义链表这种数据类型参见: https://www.doczj.com/doc/c98755106.html,/link?url=_owQzf8PRZOt9H-5oXIReh4X0ClHo6zXtRdWrdSO5YBLpKl NvkCk0qWqvFFxjgO0KzueVwEQcv9aZtVKEEH8XWSQCeVTjXvy9lxLQ_mZXeS###*/ struct Lchar{ char char_ch; struct Lchar *next; }Lchar,*p,*h,*temp,*top,*base; /*p指向终结符线性链表的头结点,h指向动态建成的终结符线性链表节点,top和base分别指向非终结符堆栈的顶和底*/

编译原理语法分析程序

编译原理实验报告 题目:对下面的文法对象,使用c语言构造它的预测分析程序;并任意给一算术表达式进行分析测试. 分析对象对象定义如下: 算术表达式→项|算术表达式+项|算术表达式-项 项→因式|项*因式|项/因式 因式→变量|(算术表达式) 变量→字母 字母→A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z 一、分析 语法分析部分我们我们采用ll(1)方法实现,采用ll(1)方法实现语法发分析要求文法满足以下要求: 一个文法能否用确定的自顶向下分析与文法中相同左部的每个产生式右部的开始符号集合有关,当有右部能=*=>ε时则与其左部非终结符的后跟符号集合也有关,此外在产生式中不存在左递归即经过压缩,无左递归,无回溯。它的基本思想是从左到右扫描源程序,同时从识别符号开始生成句子的最左推导,并只向前查看一个输入符号,便能唯一确定应选择的规则。 下面将确切地定义满足确定的自顶向下分析条件的文法即LL(1)文法及LL(1)文法的判 别并介绍如何对非LL(1)文法进行等价变换问题,也就是消除一个文法中的左递归和左公共因子。 注意: 一个文法中含有左递归和左公共因子绝对不是LL(1)文法,所以也就不可能用确定的自顶向下分析法,对此结论可以证明。然而,某些含有左递归和左公共因子的文法在通过等价变换把它们消除以后可能变为LL(1)文法,但需要用LL(1)文法的定义判别,也就是说文法中不含左递归和左公共因子,只是LL(1)文法的必要条件。 LL(1) 文法的定义(5种定义): 一个文法符号串的开始符号集合定义如下: 定义 1.设G=(VT,VN,S,P)是上下文无关文法,α是任意的文法符号串,FIRST(α)是从α推导出的串的开始符号的终结符集合。。。。 FIRST(α)={a|α=*=>aβ,a∈VT,α,β∈V*}若α=*=>ε,则规定ε∈FIRST(α).当一个文法中相同左部非终结符的右部存在能=*=>ε的情况则必须知道该非终结符的后跟符号的集合中是否含有其它右部开始符号集合的元素。为此,我们定义一个文法非终结符的后跟符号的集合如下: 定义2.设G=(VT,VN,S,P)是上下文无关文法,A∈VN,S是开始符号 FOLLOW(A)={a|S=*=>μAβ,且a∈VT,a∈FIRST(β),μ∈VT* ,β∈V+}若S=*=>μAβ,且βε, 则#∈FOLLOW(A)。也可定义为:FOLLOW(A)={a|S=*=> …Aa…,a ∈VT} 若有S=*=> …A,则规定#∈FOLLOW(A)

语法分析器实验报告

实验三语法分析器 一、实验目的: 理解和掌握LL(1)语法分析方法的基本原理;根据给出的LL(1)文法,掌握LL(1)分析表的构造及分析过程的实现,掌握语法分析方法和程序设计方法。 二、实验要求: 对每个非终极符按其产生式结构构造相应语法分析子程序,其中终极符产生匹配命令,而非终极符则产生过程调用命令。因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。其中子程序的结构与。产生式结构几乎是一致的,通过设计、编程、调试出一个具体语法分析程序。 三、实验原理: 语法分析是编译过程的核心部分。它的任务是在词法分析识别出单词符号串的基础上,分析并判定程序的语法结构是否符合语法规则。语法分析器的工作本质上是按文法的产生式,识别输入串是否是一个句子。自上而下分析法的主旨是,对任何输入串,试图用一切可能的方法,从文法开始符号出发,自上而下地为输入串建立一棵语法树。这种方法本质上是一种试探过程,是反复使用不同产生式谋求匹配输入串的过程。 对于一个文法满足以下三个条件,则称该文法为LL(1)文法。 文法不含有左递归。 对于文法中的每一个非终结符A的各个产生式的侯选首符集两两不相交。即,若A->Q1|Q2|…|Qn 则FIRST(Qi) ^FIRST(Qj)=null (i!=j) 对文法中的每个非终结符号A,若他存在某个侯选首符集包含空串,则FIRST(A)^FOLLOW(A)=null 对于一个文法满足LL(1)条件时,我们就可以对其输入串进行有效的无回溯的自上而下分析程序,这个分析程序是由一组递归过程组成的,每个过程对应文法的一个非终结符号。 四、实验步骤: 1、功能描述: 根据给定的文法,由程序生成项集族和语法分析表,对输入的源程序进行词法分析,得到语法分析的输入串,经过语法分析后得到三个栈,它们分别是状态栈,字符栈,输入栈,从而分析出输入的源程序是否有语法错误。 2、构造自己设计的小语言的语法分析器: (1) 语言的语法描述(语法规则)的设计即文法的设计; (2) 把文法形式符号中所隐含的信息内容挖掘出来并用LL或LR的资料形式(分析表)表示出来; (3) 语法分析的数据输入形式和输出形式的确定;

编译原理 语法分析器 (java完美运行版)

实验二语法分析器 一、实验目的 通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。有利于提高学生的专业素质,为培养适应社会多方面需要的能力。 二、实验内容 ◆根据某一文法编制调试LL (1 )分析程序,以便对任意输入的符号串 进行分析。 ◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分 析程序。 ◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号 以及LL(1)分析表,对输入符号串自上而下的分析过程。 三、LL(1)分析法实验设计思想及算法 ◆模块结构: (1)定义部分:定义常量、变量、数据结构。 (2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等); (3)控制部分:从键盘输入一个表达式符号串; (4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。

四、实验要求 1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。 2、如果遇到错误的表达式,应输出错误提示信息。 3、对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG (2)G->+TG|—TG (3)G->ε (4)T->FS (5)S->*FS|/FS (6)S->ε (7)F->(E) (8)F->i 输出的格式如下:

五、实验源程序 LL1.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.sql.*; import java.util.Vector; public class LL1 extends JFrame implements ActionListener { /** * */ private static final long serialVersionUID = 1L; JTextField tf1; JTextField tf2; JLabel l; JButton b0; JPanel p1,p2,p3; JTextArea t1,t2,t3; JButton b1,b2,b3;

编译原理LL(1)语法分析实验报告

学号20102798 专业软件工程姓名薛建东 实验日期2013.04.08 教师签字成绩实验报告 【实验名称】LL(1)语法分析 【实验目的】 通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练掌握开发应用程序的基本方法。 【实验内容】 ◆根据某一文法编制调试LL ( 1)分析程序,以便对任意输入的符号串进行分析。 ◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。 ◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1) 分析表,对输入符号串自上而下的分析过程。 【设计思想】 (1)、LL(1)文法的定义 LL(1)分析法属于确定的自顶向下分析方法。LL(1)的含义是:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。 LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,最后再进行句子分析。 需要预测分析器对所给句型进行识别。即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=? (2)、预测分析表构造 LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推

编译原理语法分析器实验

语法分析器的设计 一、实验内容 语法分析程序用LL(1)语法分析方法。首先输入定义好的文法书写文件(所用的文法可以用LL(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT 集的交集是不是都为空,如果是,则输入文法符合LL(1)文法,可以进行分析。对于文法: G[E]: E->E+T|T T->T*F|F F->i|(E) 分析句子i+i*i是否符合文法。 二、基本思想 1、语法分析器实现 语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。这里采用自顶向下的LL(1)分析方法。 语法分析程序的流程图如图5-4所示。 语法分析程序流程图 该程序可分为如下几步: (1)读入文法 (2)判断正误 (3)若无误,判断是否为LL(1)文法 (4)若是,构造分析表; (5)由句型判别算法判断输入符号串是为该文法的句型。 三、核心思想 该分析程序有15部分组成: (1)首先定义各种需要用到的常量和变量;

(2)判断一个字符是否在指定字符串中; (3)读入一个文法; (4)将单个符号或符号串并入另一符号串; (5)求所有能直接推出&的符号; (6)求某一符号能否推出‘& ’; (7)判断读入的文法是否正确; (8)求单个符号的FIRST; (9)求各产生式右部的FIRST; (10)求各产生式左部的FOLLOW; (11)判断读入文法是否为一个LL(1)文法; (12)构造分析表M; (13)句型判别算法; (14)一个用户调用函数; (15)主函数; 下面是其中几部分程序段的算法思想: 1、求能推出空的非终结符集 Ⅰ、实例中求直接推出空的empty集的算法描述如下: void emp(char c){ 参数c为空符号 char temp[10];定义临时数组 int i; for(i=0;i<=count-1;i++)从文法的第一个产生式开始查找 { if 产生式右部第一个符号是空符号并且右部长度为1, then将该条产生式左部符号保存在临时数组temp中 将临时数组中的元素合并到记录可推出&符号的数组empty中。 } Ⅱ、求某一符号能否推出'&' int _emp(char c) { //若能推出&,返回1;否则,返回0 int i,j,k,result=1,mark=0; char temp[20]; temp[0]=c; temp[1]='\0'; 存放到一个临时数组empt里,标识此字符已查找其是否可推出空字 如果c在可直接推出空字的empty[]中,返回1 for(i=0;;i++) { if(i==count) return(0); 找一个左部为c的产生式 j=strlen(right[i]); //j为c所在产生式右部的长度 if 右部长度为1且右部第一个字符在empty[]中. then返回1(A->B,B可推出空) if 右部长度为1但第一个字符为终结符,then 返回0(A->a,a为终结符) else

语法分析C语言程序

实验内容: 可选择LL1分析法、算符优先分析法、LR分析法之一,实现如下表达式文法的语法分析器: (1)E→E+T | E-T | T (2)T→T*F | T/F | F (3)F→P^F | P (4)P→(E) | i 实验环境: Windows XP 实验分析: (1)定义部分:定义常量、变量、数据结构。 (2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等); (3)控制部分:从键盘输入一个表达式符号串; (4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分 实验程序: #include #include using namespace std; stack symbol; stack state; char sen[50]; char sym[12][6]={//符号表 {'s','e','e','s','e','e'}, {'e','s','e','e','e','a'}, {'r','r','s','r','r','r'}, {'r','r','r','r','r','r'}, {'s','e','e','s','e','e'}, {'r','r','r','r','r','r'}, {'s','e','e','s','e','e'}, {'s','e','e','s','e','e'},

{'r','r','s','r','r','r'}, {'r','r','r','r','r','r'}, {'r','r','r','r','r','r'} }; char snum[12][6]={//数字表 {5,1,1,4,2,1}, {3,6,5,3,2,0}, {2,2,7,2,2,2}, {4,4,4,4,4,4}, {5,1,1,4,2,1}, {6,6,6,6,6,6}, {5,1,1,4,2,1}, {5,1,1,4,2,1}, {3,6,5,3,11,4}, {1,1,7,1,1,1}, {3,3,3,3,3,3}, {5,5,5,5,5,5} }; int go2[12][3]={//goto表 {1,2,3}, {0,0,0}, {0,0,0}, {0,0,0}, {8,2,3}, {0,0,0}, {0,9,3}, {0,0,10}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }; void action(int i,char *&a,char &how,int &num,char &A,int &b)//action函数[i,a] { int j; switch(*a) { case 'i': j=0;break; case '+': j=1;break; case '*': j=2;break; case '(':

基于LR(1)的语法分析程序报告

基于LR(1)的语法分析程序 1.设计目的: 设计、编制和调试一个典型的LR(1)分析器,进一步掌握LR(1)语法分析方法,掌握用预测分析方法分析LR(1)文法的具体过程,加深对LR(1)文法和预测分析方法的理解。 2.设计要求: (1)根据LR(1)分析法编写一个语法分析程序,.输入已给定文法,直接输入根据己知文法构造的LR(1)分析表。 (2)对于输入的符号串,所编制的语法分析程序应能正确判断此串是否为文法的句子,并要求输出分析过程。 3.设计过程: 3.1 LR(1)文法的含义: LR分析法的规约过程是规范推倒的逆过程,所以LR分析过程是一种规范规约的逆过程,L表示从左到右扫描输入串,R表示最左规约(即最右推导的逆过程),括号中的1表示向右查看输入符号数为1。LR(1)项目可以看成两个部分组成,一部分和LR (0)项目相同,这部分成为心,另一部分为向前搜索符集合。所以只有当面临的输入符属于向前搜索符的集合,才做规约动作,其他情况均出错。LR(1)方法恰好解决SLR(1)方法在某些情况下存在的无效规约问题。 3.2 设计思想: 根据自身实际情况,给定了编译原理书中的一个LR(1)文法,求出其项目集合转换函数,从而得出此LR(1)文法的分析表,在程序中直接输出此分析表,并根据分析表中的内容可对输入的符

号串进行分析,判断是接受还是出错,从而得出该输入的符号串是否为文法的一个句子。 3.3 算法描述: 1.CLOSURE(I)的构造 CLOSURE(I)表示和I中项目可以识别同样活前缀的所有项目的集合。它可以有以下方法得到: (1)I中的所有项目都属于CLOSURE(I); (2)若项目[A→a.Bβ,a]属于CLOSURE(I),B→ξ是一个产生式,那么,对于FIRST<βa>中的每一个中介符b,如果[β→.ξ,b]原来不在CLOSURE(I)中,则把它加进去; (3)重复执行步骤(2),直到CLOSURE(I)不再增大为止。 2.GO(I,X)的构造 GO(I,X)=CLOSURE(J) 其中J={任何形如[A→aX.Β,a]的项目[A→a.X.Β,a]属于I} 3.FIRST集合的构造 在这个程序中使用的是FIRST(βa),这基于每一个非终结符的FRIST集合(终结符的FIRST就是它本身)。所以需要对每一个非终结符构造其FIRST集合。 方法如下: 连续使用下面的规则,直到每个集合FIRST不再增大为止。 (1)若X属于V T,则FIRST(X)={X}。 (2)若X属于V N,且有产生式X→a…,则把A加入到FIRST(X)中;若X→ξ也是一条产生式,则把ξ也加入到FIRST 中。 4.LR(1)分析表的构造 在实现GO(I,X)时,记录下状态的转化。得到分析表中的移进部分。然后再扫描所有的项目集,找到其中包含归约项目的哪些项目集,根据其中项目,得到分析表中那些鬼月的部分。 4 设计内容 4.1 主要变量说明: #define SIZE 20 //宏定义,定义sSIZE为12 #define sSIZE 12 //宏定义,定义sSIZE为12

LL(1)语法分析程序实验报告

1.设计要求 (1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止; (2)输入已知文法,由程序自动生成它的LL(1)分析表; (3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。 2.分析 该程序可分为如下几步: (1)读入文法 (2)判断正误 (3)若无误,判断是否为LL(1)文法 (4)若是,构造分析表; (5)由总控算法判断输入符号串是否为该文法的句型。 3.流程图

4.源程序 /******************************************* 语法分析程序 作者:龚勋刘栋罗晓波 学号:200131500342 200131500350 200131500351 计科系13班 ********************************************/ #include #include #include /*******************************************/ int count=0; /*分解的产生式的个数*/ int number; /*所有终结符和非终结符的总数*/ char start; /*开始符号*/ char termin[50]; /*终结符号*/ char non_ter[50]; /*非终结符号*/ char v[50]; /*所有符号*/ char left[50]; /*左部*/ char right[50][50]; /*右部*/ char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/ char select[50][50]; /*各单个产生式的SELECT集合*/ char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/ char empty[20]; /*记录可直接推出^的符号*/ char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/ int validity=1; /*表示输入文法是否有效*/ int ll=1; /*表示输入文法是否为LL(1)文法*/ int M[20][20]; /*分析表*/ char choose; /*用户输入时使用*/ char empt[20]; /*求_emp()时使用*/ char fo[20]; /*求FOLLOW集合时使用*/ /******************************************* 判断一个字符是否在指定字符串中 ********************************************/ int in(char c,char *p) { int i; if(strlen(p)==0) return(0);

语法分析器实验报告

语法分析器的设计实验报告 一、实验内容 语法分析程序用LL(1)语法分析方法。首先输入定义好的文法书写文件(所用的文法可以用LL(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT 集的交集是不是都为空,如果是,则输入文法符合LL(1)文法,可以进行分析。对于文法: G[E]: E->E+T|T T->T*F|F F->i|(E) 分析句子i+i*i是否符合文法。 二、基本思想 1、语法分析器实现 语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。这里采用自顶向下的LL(1)分析方法。 语法分析程序的流程图如图5-4所示。 语法分析程序流程图 该程序可分为如下几步: (1)读入文法 (2)判断正误 (3)若无误,判断是否为LL(1)文法 (4)若是,构造分析表; (5)由句型判别算法判断输入符号串是为该文法的句型。 三、核心思想 该分析程序有15部分组成: (1)首先定义各种需要用到的常量和变量;

(2)判断一个字符是否在指定字符串中; (3)读入一个文法; (4)将单个符号或符号串并入另一符号串; (5)求所有能直接推出&的符号; (6)求某一符号能否推出‘& ’; (7)判断读入的文法是否正确; (8)求单个符号的FIRST; (9)求各产生式右部的FIRST; (10)求各产生式左部的FOLLOW; (11)判断读入文法是否为一个LL(1)文法; (12)构造分析表M; (13)句型判别算法; (14)一个用户调用函数; (15)主函数; 下面是其中几部分程序段的算法思想: 1、求能推出空的非终结符集 Ⅰ、实例中求直接推出空的empty集的算法描述如下: void emp(char c){ 参数c为空符号 char temp[10];定义临时数组 int i; for(i=0;i<=count-1;i++)从文法的第一个产生式开始查找 { if 产生式右部第一个符号是空符号并且右部长度为1, then将该条产生式左部符号保存在临时数组temp中 将临时数组中的元素合并到记录可推出&符号的数组empty中。 } Ⅱ、求某一符号能否推出'&' int _emp(char c) { //若能推出&,返回1;否则,返回0 int i,j,k,result=1,mark=0; char temp[20]; temp[0]=c; temp[1]='\0'; 存放到一个临时数组empt里,标识此字符已查找其是否可推出空字 如果c在可直接推出空字的empty[]中,返回1 for(i=0;;i++) { if(i==count) return(0); 找一个左部为c的产生式 j=strlen(right[i]); //j为c所在产生式右部的长度 if 右部长度为1且右部第一个字符在empty[]中. then返回1(A->B,B可推出空) if 右部长度为1但第一个字符为终结符,then 返回0(A->a,a为终结符) else

实验二--语法分析程序的设计-

实验二语法分析程序的设计 姓名:学号:专业班级 一、实验目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析中预测分析方法。 二、实验内容 设计一个文法的预测分析程序,判断特定表达式的正确性。 三、实验要求 1、给出文法如下: G[E] E->T|E+T; T->F|T*F; F->i|(E); 2、根据该文法构造相应的LL(1)文法及LL(1)分析表,并为该文法设计预测分析程序, 利用C语言或C++语言或Java语言实现; 3、利用预测分析程序完成下列功能: 1)手工将测试的表达式写入文本文件,每个表达式写一行,用“;”表示结束; 2)读入文本文件中的表达式; 3)调用实验一中的词法分析程序搜索单词; 4)把单词送入预测分析程序,判断表达式是否正确(是否是给出文法的语言),若错误,应给出错误信息; 5)完成上述功能,有余力的同学可以进一步完成通过程序实现对非LL(1)文法到LL(1)文法的自动转换(见实验二附加资料1)。 四、实验环境 PC微机 DOS操作系统或Windows 操作系统 Turbo C 程序集成环境或Visual C++ 程序集成环境 五、实验步骤 1、分析文法,将给出的文法转化为LL(1)文法; 2、学习预测分析程序的结构,设计合理的预测分析程序; 3、编写测试程序,包括表达式的读入和结果的输出; 4、测试程序运行效果,测试数据可以参考下列给出的数据。 六、测试数据

输入数据: 编辑一个文本文文件expression.txt ,在文件中输入如下内容: 正确结果: (1)10; 输出:正确 (2)1+2; 输出:正确 (3)(1+2)*3+(5+6*7); 输出:正确 (4)((1+2)*3+4 输出:错误 (5)1+2+3+(*4+5) 输出:错误 (6)(a+b)*(c+d) 输出:正确 (7)((ab3+de4)**5)+1 输出:错误 七、源代码 import java.util.*; import java.io.*; public class test2 { static String[] key_word = { "main", "if", "then", "while", "do", "int", "else" }; static String[] cal_word = { "+", "-", "*", "/", "<", ">", "{", "}", "(", ")", "[", "]", "==", "!=", "!", "=", ">=", "<=", "+=", "-=", "*=", "/=", ";" }; /* * 给定文法G[E]: E->T|E+T; T->F|T*F; F->i|(E); */ static String[] gram = { "E->TA", "A->+TA", "A->@", "T->FB", "B->*FB", "B->@", "F->P", "F->(E)" }; static String[] followE = { ")", "#" };

相关主题
文本预览
相关文档 最新文档