编译语言-语法分析器的设计
国开电大 编译原理 实验4:语法分析实验报告

国开电大编译原理实验4:语法分析实
验报告
1. 实验目的
本实验的目的是研究和掌握语法分析的原理和实现方法。
2. 实验内容
本次实验主要包括以下内容:
- 设计并实现自顶向下的LL(1)语法分析器;
- 通过语法分析器对给定的输入串进行分析,并输出相应的分析过程;
- 编写测试用例,验证语法分析器的正确性。
3. 实验步骤
3.1 设计LL(1)文法
首先,根据实验要求和给定的语法规则,设计LL(1)文法。
3.2 构建预测分析表
根据所设计的LL(1)文法,构建预测分析表。
3.3 实现LL(1)语法分析器
根据预测分析表,实现自顶向下的LL(1)语法分析器。
3.4 对输入串进行分析
编写程序,通过LL(1)语法分析器对给定的输入串进行分析,并输出相应的分析过程和结果。
3.5 验证语法分析器的正确性
设计多组测试用例,包括正确的语法串和错误的语法串,验证语法分析器的正确性和容错性。
4. 实验结果
经过实验,我们成功设计并实现了自顶向下的LL(1)语法分析器,并对给定的输入串进行了分析。
实验结果表明该语法分析器具有较好的准确性和容错性。
5. 实验总结
通过本次实验,我们对语法分析的原理和实现方法有了更深入的了解。
同时,我们也学会了如何设计并实现自顶向下的LL(1)语
法分析器,并验证了其正确性和容错性。
这对于进一步研究编译原理和深入理解编程语言的语法结构具有重要意义。
6. 参考资料
- 《编译原理与技术》
- 课程实验文档及代码。
编译原理词法分析器语法分析课程设计范本

《编译原理词法分析器语法分析课程设计-《编译原理》课程设计院系信息科学与技术学院专业软件工程年级级学号 2723姓名林苾湲西南交通大学信息科学与技术学院12月目录课程设计1 词法分析器 (2)设计题目 (2)设计内容 (2)设计目的 (2)设计环境 (2)需求分析 (2)概要设计 (2)详细设计 (4)编程调试 (5)测试 (11)结束语 (13)课程设计2 赋值语句的解释程序设计 (14)设计题目 (14)设计内容 (14)设计目的 (14)设计环境 (14)需求分析 (15)概要设计 (16)详细设计 (16)编程调试 (24)测试 (24)结束语 (25)课程设计一词法分析器设计一、设计题目手工设计c语言的词法分析器(能够是c语言的子集)。
二、设计内容处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。
三、设计目的了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。
四、设计环境该课程设计包括的硬件和软件条件如下:.硬件(1)Intel Core Duo CPU P8700(2)内存4G.软件(1)Window 7 32位操作系统(2)Microsoft Visual Studio c#开发平台.编程语言C#语言五、需求分析.源程序的预处理:源程序中,存在许多编辑用的符号,她们对程序逻辑功能无任何影响。
例如:回车,换行,多余空白符,注释行等。
在词法分析之前,首先要先剔除掉这些符号,使得词法分析更为简单。
.单词符号的识别并判断单词的合法性:将每个单词符号进行不同类别的划分。
单词符号能够划分成5中。
(1)标识符:用户自己定义的名字,常量名,变量名和过程名。
(2)常数:各种类型的常数。
(3) 保留字(关键字):如if、else、while、int、float 等。
(4) 运算符:如+、-、*、<、>、=等。
编译原理语法分析器实验报告

编译原理语法分析器实验报告西安邮电大学编译原理实验报告学院名称:计算机学院****:***实验名称:语法分析器的设计与实现班级:计科1405班学号:04141152时间:2017年5月12日把SELECT (i)存放到temp中结果返回1;1.构建好的预测分析表2.语法分析流程图一.实验结果正确运行结果:错误运行结果:二.设计技巧和心得体会这次实验编写了一个语法分析方法的程序,但是在LL(1)分析器的编写中我只达到了最低要求,就是自己手动输入的select集,first集,follow集然后通过程序将预测分析表构造出来,然后自己编写总控程序根据分析表进行分析。
通过本次试验,我能够设计一个简单的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
还能选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序。
三.源代码package com.LL1;import java.util.ArrayDeque;import java.util.Deque;/*** LL1文法分析器,已经构建好预测分析表,采用Deque实现* Created by HongWeiPC on 2017/5/12.*/public class LL1_Deque {//预测分析表private String[][] analysisTable = new String[][]{{"TE'", "", "", "TE'", "", ""},{"", "+TE'", "", "", "ε", "ε"},{"FT'", "", "", "FT'", "", ""},{"", "ε", "*FT'", "", "ε", "ε"},{"i", "", "", "(E)", "", ""}};//终结符private String[] VT = new String[]{"i", "+", "*", "(", ")", "#"};//非终结符private String[] VN = new String[]{"E", "E'", "T", "T'", "F"};//输入串strTokenprivate StringBuilder strToken = new StringBuilder("i*i+i");//分析栈stackprivate Deque<String> stack = new ArrayDeque<>();//shuru1保存从输入串中读取的一个输入符号,当前符号private String shuru1 = null;//X中保存stack栈顶符号private String X = null;//flag标志预测分析是否成功private boolean flag = true;//记录输入串中当前字符的位置private int cur = 0;//记录步数private int count = 0;public static void main(String[] args) {LL1_Deque ll1 = new LL1_Deque();ll1.init();ll1.totalControlProgram();ll1.printf();}//初始化private void init() {strToken.append("#");stack.push("#");System.out.printf("%-8s %-18s %-17s %s\n", "步骤", "符号栈", "输入串", "所用产生式");stack.push("E");curCharacter();System.out.printf("%-10d %-20s %-20s\n", count, stack.toString(), strToken.substring(cur, strToken.length()));}//读取当前栈顶符号private void stackPeek() {X = stack.peekFirst();}//返回输入串中当前位置的字母private String curCharacter() {shuru1 = String.valueOf(strToken.charAt(cur));return shuru1;}//判断X是否是终结符private boolean XisVT() {for (int i = 0; i < (VT.length - 1); i++) {if (VT[i].equals(X)) {return true;}}return false;}//查找X在非终结符中分析表中的横坐标private String VNTI() {int Ni = 0, Tj = 0;for (int i = 0; i < VN.length; i++) {if (VN[i].equals(X)) {Ni = i;}}for (int j = 0; j < VT.length; j++) {if (VT[j].equals(shuru1)) {Tj = j;}}return analysisTable[Ni][Tj];}//判断M[A,a]={X->X1X2...Xk}//把X1X2...Xk推进栈//X1X2...Xk=ε,不推什么进栈private boolean productionType() {return VNTI() != "";}//推进stack栈private void pushStack() {stack.pop();String M = VNTI();String ch;//处理TE' FT' *FT'特殊情况switch (M) {case "TE'":stack.push("E'");stack.push("T");break;case "FT'":stack.push("T'");stack.push("F");break;case "*FT'":stack.push("T'");stack.push("F");stack.push("*");break;case "+TE'":stack.push("E'");stack.push("T");stack.push("+");break;default:for (int i = (M.length() - 1); i >= 0; i--) {ch = String.valueOf(M.charAt(i));stack.push(ch);}break;}System.out.printf("%-10d %-20s %-20s %s->%s\n", (++count), stack.toString(), strToken.substring(cur, strToken.length()), X, M);}//总控程序private void totalControlProgram() {while (flag) {stackPeek(); //读取当前栈顶符号令X=栈顶符号if (XisVT()) {if (X.equals(shuru1)) {cur++;shuru1 = curCharacter();stack.pop();System.out.printf("%-10d %-20s %-20s \n", (++count), stack.toString(), strToken.substring(cur, strToken.length()));} else {ERROR();}} else if (X.equals("#")) {if (X.equals(shuru1)) {flag = false;} else {ERROR();}} else if (productionType()) {if (VNTI().equals("")) {ERROR();} else if (VNTI().equals("ε")) {stack.pop();System.out.printf("%-10d %-20s %-20s %s->%s\n", (++count), stack.toString(), strToken.substring(cur, strToken.length()), X, VNTI());} else {pushStack();}} else {ERROR();}}}//出现错误private void ERROR() {System.out.println("输入串出现错误,无法进行分析");System.exit(0);}//打印存储分析表private void printf() {if (!flag) {System.out.println("****分析成功啦!****");} else {System.out.println("****分析失败了****");}}}。
语法分析器设计实验报告

语法分析器设计实验报告一、引言语法分析器是编译器中的重要组成部分,其主要功能是根据给定的文法规则,对输入的程序代码进行语法分析,判断其是否符合语法规范。
本实验旨在设计一个简单的语法分析器,通过实际实现一个基于LL(1)文法的语法分析器,深入了解语法分析的原理和实现方法。
二、实验目标本实验的目标是设计一个能够接受一个输入的程序代码并进行语法分析的程序。
具体而言,需要实现以下功能:1. 构建一个文法规则集合,用于描述程序代码的语法规范;2. 设计并实现一个LL(1)分析表,用于存储语法分析所需的预测分析表;3. 实现语法分析器,能够根据输入的程序代码,逐步地进行语法分析,并输出相应的结果。
三、实验环境本实验使用的是Java语言进行实现,操作系统环境为Windows 10。
使用的集成开发环境为Eclipse。
四、实验步骤1. 设计文法规则集合在语法分析器设计中,首先需要设计一个文法规则集合,用于描述需要分析的程序代码的语法规范。
文法规则集合的设计要符合LL(1)文法的要求,即每个非终结符的产生式至多有一个与输入符号串首符号相关的产生式。
2. 构建LL(1)分析表根据文法规则集合,构建一个LL(1)分析表,用于存储语法分析所需的预测分析表。
LL(1)分析表是一个二维表,其中行表示非终结符,列表示终结符。
表中的每个元素表示相应的产生式编号,用于指示语法分析器在分析过程中应该使用哪个产生式。
构建LL(1)分析表的方法包括:- 遍历文法规则集合,计算每个非终结符的FIRST集合和FOLLOW集合;- 根据计算得到的FIRST集合和FOLLOW集合,填充LL(1)分析表。
3. 实现语法分析器根据LL(1)分析表,实现一个语法分析器。
语法分析器的输入是一个程序代码,输出是语法分析器的分析结果。
实现语法分析器的主要过程包括:- 初始化分析栈,将文法规则的开始符号入栈;- 从输入的程序代码中读取下一个终结符;- 如果分析栈的栈顶是非终结符,根据LL(1)分析表中对应的产生式编号,将产生式右部的符号依次入栈;- 如果分析栈的栈顶是终结符,并且与输入的终结符相同,则将该终结符出栈,并继续读取下一个终结符;- 重复上述过程,直到分析栈为空或者无法继续推导。
语法分析器设计实验报告

学号《编译原理》实验2:语法分析器设计学生姓名专业、班级指导教师赵璐成绩计算机与信息工程学院2018 年11 月27 日一、实验目的1.理解语法分析程序的功能。
2.熟悉语法分析程序的设计原理和构造方法。
3.掌握递归下降语法分析程序的构造方法。
4.设计一个递归下降的语法分析器,作为实验一构造的词法分析器的下一步编译工具,能语法分析前一步词法分析器输出的单词符号序列。
二、实验要求1.根据书P206给出的简单语言的语法规则,编写C或C++语言源程序,实现针对该简单语言的递归下降的语法分析器;2.独立做实验,输入、调试所编程序;3.实验结束后,根据实验报告模板编写实验报告。
三、实验内容和步骤用Visual C++作为实验开发环境,创建一个Win32 Console Application工程,工程名为你的学号,添加三个文件:(1)存储结构定义:以ParserDef.h和LexerDef.h为文件名;(2)基本操作的算法:以ParserAlgo.h和LexerAlgo.h为文件名;(3)调用基本操作的主程序:以ParserMain.cpp为文件名。
编写程序:(1)文件LexerDef.h和LexerAlgo.h为实验一的内容。
(2)文件ParserDef.h定义语法分析所需的全局变量等。
(3)文件ParserAlgo.h实现对语法规则中各语法成分的分析子算法。
(4)文件ParserMain.cpp实现针对P206简单语言语法规则的递归下降语法分析器。
源程序代码:=============================ParserDef.h================================ int kk;#define _KEY_WORD_END "waiting for your expanding"char * rwtab[]={"begin","if","then","while","do","end",_KEY_WORD_END};char input[255];char token[255]="";int p_input;int p_token;char ch;============================ParserAlgo.h================================ char prog[80];int syn,p,m,n,sum=0;void scaner() {m=0;for(n=0; n<8; n++) token[n]=NULL;ch=prog[p++];while(ch==' ') ch=prog[p++];if((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')) {while((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')||(ch>='0' && ch<='9')) {token[m++]=ch;ch=prog[p++];}token[m++]='\0';syn=10;p=p-1; //回退一个字符for(n=0; n<6; n++) {if(strcmp(token,rwtab[n])==0) {syn=n+1;break;}}} else if(ch>='0' && ch<='9') {sum=0;while(ch>='0' && ch<='9') {sum=sum*10+ch-'0';ch=prog[p++];}p=p-1;syn=11;} else {switch(ch) {case '<':m=0;token[m++]=ch;ch=prog[p];if(ch=='>') {syn=21;token[m++]=ch;} else if(ch=='=') {syn=22;token[m++]=ch;} else {syn=20;p=p-1;}p=p+1;token[m]='\0';break;case '>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=24;token[m++]=ch;} else {syn=23;p=p-1;}break;case ':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=18;token[m++]=ch;} else {syn=17;p=p-1;}break;case '+':syn=13;token[0]=ch;break;case '-':syn=14;token[0]=ch;break;case '*':syn=15;token[0]=ch;break;case '/':syn=16;token[0]=ch;break;case ';':syn=26;token[0]=ch;break;case '(':syn=27;token[0]=ch;break;case ')':syn=28;token[0]=ch;break;case '=':syn=25;token[0]=ch;break;case '#':syn=0;token[0]=ch;break;default:syn=-1;}}}============================ParserMain.cpp============================== #include<stdio.h>#include<stdlib.h>#include<string.h>#include"LexerDef.h"#include"ParserDef.h"#include"LexerAlgo.h"#include"ParserAlgo.h"void lrparser();void yucu();void statement();void expression();void term();void factor();void lrparser() {if (syn==1) { //beginscaner();yucu();if (syn==6) { //endscaner();if (syn==0 && kk==0) printf("success \n");} else {if(kk!=1) printf("error,lose 'end' ! \n");kk=1;}} else {printf("error,lose 'begin' ! \n");kk=1;}return;}void yucu() {statement();while(syn==26) {scaner();statement();}return;}void statement() {if (syn==10) { //为标识符scaner();if (syn==18) { //为:=scaner();expression();} else {printf("error!");kk=1;}} else {printf("error!");kk=1;}return;}void expression() {term();while(syn==13 || syn==14) {scaner();term();}return;}void term() {factor();while(syn==15 || syn==16) {scaner();factor();}return;}void factor() {if(syn==10 || syn==11)scaner(); //为标识符或整常数时,读下一个单词符号else if(syn==27) {scaner();expression();if(syn==28)scaner();else {printf(" ')' 错误\n");kk=1;}} else {printf("表达式错误\n");kk=1;}return;}void main() {p=0;printf("********************语法分析程序***************\n");printf("请输入源程序:\n");do {scanf("%c",&ch);prog[p++]=ch;} while(ch!='#');p=0;scaner();lrparser();printf("语法分析结束!\n");}四、解答下列问题(1)简述该语法分析器的算法思想。
编译原理语法分析器

编译原理语法分析器编译原理语法分析器是编译器中的重要组成部分,它负责将源代码解析成抽象语法树,为后续的语义分析和代码生成做准备。
本文将介绍语法分析器的原理、分类和常用算法。
一、语法分析器的原理语法分析器的主要任务是根据给定的文法定义,将源代码解析成一个个语法单元,并构建出一棵抽象语法树。
它通过递归下降、预测分析和LR分析等算法来实现。
1. 递归下降法递归下降法是一种基于产生式的自顶向下分析方法。
它从文法的开始符号出发,通过不断地推导和回溯,逐步地构建抽象语法树。
递归下降法易于理解和实现,但对左递归和回溯有一定的局限性。
2. 预测分析法预测分析法也是自顶向下的分析方法,它通过预测下一个输入符号来选择适当的产生式进行推导。
为了提高效率,预测分析法使用预测分析表来存储各个非终结符和终结符的关系。
3. LR分析法LR分析法是一种自底向上的分析方法,它使用LR自动机和LR分析表来进行分析。
LR自动机是一个有限状态控制器,通过状态转移和规约动作来解析源代码。
LR分析表存储了状态转移和规约的规则。
二、语法分析器的分类根据语法分析器的特性和实现方式,可以将其分为LL分析器和LR 分析器。
1. LL分析器LL分析器是基于递归下降法和预测分析法的一类分析器。
它从左到右、从左到右地扫描源代码,并根据预测分析表进行推导。
常见的LL分析器有LL(1)分析器和LL(k)分析器。
2. LR分析器LR分析器是基于LR分析法的一类分析器。
它先通过移进-归约的方式建立一棵语法树,然后再进行规约操作。
LR分析器具有强大的语法处理能力,常见的LR分析器有LR(0)、SLR(1)、LR(1)和LALR(1)分析器。
三、常用的语法分析算法除了递归下降法、预测分析法和LR分析法,还有一些其他的语法分析算法。
1. LL算法LL算法是一种递归下降法的改进算法,它通过构造LL表和预测分析表实现分析过程。
LL算法具有很好的可读性和易于理解的特点。
2. LR算法LR算法是一种自底向上的分析方法,它通过建立LR自动机和构造LR分析表来进行分析。
语法分析器的设计

语法分析器的设计1.设计原则在设计语法分析器时,应遵循以下原则:-维护清晰的分析策略:选择合适的文法类别,以便能够使用适当的分析策略,如自上而下分析、自下而上分析或混合分析等。
-使用适当的数据结构:选择合适的数据结构来表示词法单元流和语法树,以提高分析效率和易读性。
-错误处理机制:有效地处理语法错误,提供有用的错误信息以帮助开发人员进行调试和修复。
-可扩展性和可维护性:设计一个灵活的框架,使得分析器能够适应新的语言特性和文法规则,并便于维护和修改。
2.文法规则分析例如,下面是一个简单的四则运算表达式的文法规则:```<expression> ::= <term> '+' <expression><term> '-' <expression<term<term> ::= <factor> '*' <term><factor> '/' <term<factor<factor> ::= '(' <expression> ')'<number<number> ::= [0-9]+```在编写语法分析器时,需要将这些规则翻译为具体的代码逻辑。
3.自上而下分析自上而下分析是一种从文法规则的最上层开始,逐步展开产生式规则,并根据输入的词法单元流进行匹配的分析方法。
以下是一个简单的自上而下分析的伪代码示例:```function parseExpression(:term = parseTermif currentToken.type == '+':match('+')expression = parseExpressionreturn BinaryExpression('+', term, expression)else if currentToken.type == '-':match('-')expression = parseExpressionreturn BinaryExpression('-', term, expression) else:return termfunction parseTerm(:factor = parseFactorif currentToken.type == '*':match('*')term = parseTermreturn BinaryExpression('*', factor, term) else if currentToken.type == '/':match('/')term = parseTermreturn BinaryExpression('/', factor, term) else:return factorfunction parseFactor(:if currentToken.type == '(':match('(')expression = parseExpressionmatch(')')return expressionelse if currentToken.type == 'number':number = currentToken.valuematch('number')return NumberLiteral(number)else:error("Invalid factor")function match(expectedType):if currentToken.type == expectedType:currentToken = getNextTokenelse:error("Unexpected token: " + currentToken.type)```代码示例中的`currentToken`表示当前正在处理的词法单元,`getNextToken(`获取下一个词法单元。
语法分析器实验报告

语法分析器的设计实验报告一、实验内容语法分析程序用LL(1)语法分析方法。
首先输入定义好的文法书写文件(所用的文法可以用LL(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT集的交集是不是都为空,如果是,则输入文法符合LL(1)文法,可以进行分析。
对于文法:G[E]:E->E+T|TT->T*F|FF->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中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三语法分析器的设计一、实验内容设计、编写和调试构造LR(0)项目集规范簇或实现基于LR分析表对给定的符号串进行LR 分析的程序。
以下两个内容任选其中一项:(1)对于给定的文法,实现构造识别该文法全部活前缀DFA的程序。
(2)对于给定的LR分析表和符号串,设计程序以实现所输入符号串是否为合法符号串。
要求用JAVA语言编程。
(可参考实验指导书P149至P156)二、程序代码AnalysisOfGrammer.javapackage analysis;import javax.swing.*;import javax.swing.table.DefaultTableModel;import java.awt.*;import java.awt.event.*;import java.io.*;import java.util.LinkedList;publicclass AnalysisOfGrammer extends JApplet{private JFileChooser jfc = new JFileChooser(new File("."));private JButton jbt1 = new JButton("打开文法文件");private JButton jbt2 = new JButton("构造LR规范簇");private JButton jbt3 = new JButton("构造LR分析表");private JButton jbt4 = new JButton("清空");private JButton jbt5 = new JButton("退出");private JLabel jl1 = new JLabel("LR(0)项目集规范簇");private JLabel jl2 = new JLabel("LR(0)分析表");private JPanel p3 = new JPanel();private JTextArea jta1 = new JTextArea();private String[] grammer = new String[50];privateint count = 0;private LinkedList<ViablePrefixe>list = new LinkedList<ViablePrefixe>();private Object content[][] = new Object[100][4];int num1 = 0;String[][] cache = new String[50][100];int[] location = newint[50];int back = 0;publicvoid clear1(){grammer = null;}publicvoid clear2(){num1 = 0;list = null;content = null;cache = null;location = null;back = 0;}public AnalysisOfGrammer(){JPanel p1 = new JPanel();p1.setLayout(new GridLayout(1,5));p1.add(jbt1);p1.add(jbt2);p1.add(jbt3);p1.add(jbt4);p1.add(jbt5);add(p1,BorderLayout.NORTH);JPanel p4 = new JPanel();p4.setLayout(new GridLayout(1,2));JPanel p2 = new JPanel();p2.setLayout(new BorderLayout());p2.add(new JLabel("文法为:"),BorderLayout.NORTH);p2.add(new JScrollPane(jta1),BorderLayout.CENTER);p4.add(p2);p4.add(p3);add(p4,BorderLayout.CENTER);jbt1.addActionListener(new ActionListener(){publicvoid actionPerformed(ActionEvent e){jta1.setText("");open();}});jbt2.addActionListener(new ActionListener(){publicvoid actionPerformed(ActionEvent e){if(jta1.getText().equals(""))JOptionPane.showMessageDialog(null, "请打开文法文件!");else{DNF();list.get(1).setNextState("接受态");for(int k = 0 ; k<list.size() ; k++){content[k][0] = list.get(k).getState();content[k][1] = list.get(k).getProjectSet();content[k][2] = list.get(k).getNextSign();content[k][3] = list.get(k).getNextState();}String columnName[] = {"状态","项目集","后继符号","后继状态"};JTable table = new JTable(content,columnName);p3.setLayout(new BorderLayout());p3.add(jl1,BorderLayout.NORTH);p3.add(new JScrollPane(table),BorderLayout.CENTER);}clear2();}});}publicint getleng(String[] s){//获得一个字符串数组的真实长度int len = 0;while(s[len]!=null){len++;}return len;}publicvoid DNF(){//自动机的构成int c = 0;int[] flag = newint[100];String start = "S'-.>"+grammer[0].substring(0, 1);flag[num1] = createI(start);//初态集建立location[num1] = getleng(cache[num1]);while(back<= num1){if(c<location[back] &&flag[back] == 0){num1++;list.get(back).setNextState(list.get(back).getNextState()+"S"+num1+" ");flag[num1] = createI(cache[back][c]);location[num1] = getleng(cache[num1]);c++;}else{back++;c = 0;}}}publicint createI(String t){//生成状态集int end = 0;String s = addPoint(t);String head = findNext(s);String state = "S"+num1;;String nextsign="";String nextstate="";boolean[] gra = newboolean[count];int c = 1;int loop = 0;for(int k = 0 ; cache[k][0] != null; k++){if(cache[k][0].equals(s)){loop = k;end = 2;break;}}if(end == 2){//更改后继状态String old = list.get(back).getNextState();String sta = "S"+num1;String renew = "";int staleng = sta.length();for(int k = 0 ; k<old.length()-staleng+1; k++ ){if(old.substring(k,k+staleng).matches(sta)||old.equals("归约")){num1--;renew =old.substring(0,k-1)+"S"+loop+old.substring(k+staleng+1, old.length())+" ";list.get(back).setNextState(renew);break;}elseif(old.equals("归约")){num1--;renew =old.substring(0,k-1)+"S"+loop+old.substring(k+staleng+1, old.length())+" ";list.get(back).setNextState(renew);break;}}return end;}cache[num1][0] = s;String set = cache[num1][0] + " ";if(num1<list.size()){nextsign=list.get(num1).getNextSign();nextstate=list.get(num1).getNextState();set = list.get(num1).getProjectSet()+cache[num1][0] + " ";}if(findNext(s).equals("#")){set = s;nextsign = "#";nextstate = "归约";ViablePrefixe o = new ViablePrefixe(state,set,nextsign,nextstate);list.add(o);return 1;}else{while(true){int i = 0;for(; i<count; i++){if(grammer[i].substring(0,1).equals(head)&&gra[i]!=true){set = set + addPoint(grammer[i]) +" ";cache[num1][c++] = addPoint(grammer[i]);if(findNext(addPoint(grammer[i])).matches("[A-Z]")&&gra[i]!=true){gra[i] = true;head = findNext(addPoint(grammer[i]));break;}}}//for循环结束if(i>= count&&head.equals(findNext(s).substring(0,1))) break;elseif(i>= count){head = grammer[0].substring(0,1);}}//while循环结束int cc = 0; //设置下一状态的值String[] nextS = new String[50];for(int i = 0 ; cache[num1][i]!=null; i++){int j = 0;boolean f = false;for(; nextS[j]!=null;j++){if(findNext(cache[num1][i]).equals(nextS[j])){f = true; break;}}//for j 的循环结束,查找有无相同的后继符号,f作为标记,相同的符号跳过,不同的记录下来,放在nestS[]里if(f != true){nextS[cc++] = findNext(cache[num1][j]);nextsign = nextsign+findNext(cache[num1][j])+" ";}}//for i循环结束ViablePrefixe o = new ViablePrefixe(state,set,nextsign,nextstate);list.add(o);}return end;}publicint show(String s, String[] grammer){//文法的拆分函数,显示在界面上,返回值是文法的条数boolean lastSign = false;//上一符号为\nint flag1 = 0;//上一符号位置int count = 0;String str = s.substring(flag1, flag1+3);for(int i = 0 ; i<s.length() ; i++){if(s.substring(i, i+1).equals("|")){if(lastSign)grammer[count++] = str + s.substring(flag1, i);elsegrammer[count++] = s.substring(flag1, i);flag1 = i + 1;lastSign = true;}elseif(s.substring(i, i+1).equals("\n")){if(lastSign)grammer[count++] = str + s.substring(flag1, i);elsegrammer[count++] = s.substring(flag1, i);flag1 = i+1;if(flag1+3 <s.length())str = s.substring(flag1, flag1+3);lastSign = false;}elseif(s.substring(i, i+1).equals("\r")){if(lastSign)grammer[count++] = str + s.substring(flag1, i);elsegrammer[count++] = s.substring(flag1, i);i++;flag1 = i+1;if(flag1+3 <s.length())str = s.substring(flag1, flag1+3);lastSign = false;}}return count;}privatevoid open(){//打开文件String s ="";if(jfc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) s = open(jfc.getSelectedFile());count = show(s,grammer);for(int i = 0 ; grammer[i]!=null ; i++){jta1.append(grammer[i]);jta1.append("\n");}}private String open(File file){//打开文件String content1 = "";try{BufferedInputStream in =new BufferedInputStream(new FileInputStream(file));byte[] b = newbyte[in.available()];in.read(b,0,b.length);content1 = new String(b,0,b.length);in.close();}catch(IOException ex){jta1.setText("Error opening " + file.getName());}return content1;}privatestatic String addPoint(String m){//在文法中添加.String t="";int i;for(i = 0 ; i<m.length() ; i++){if(m.substring(i,i+1).equals(".")){if(i == m.length()-1)return m;t =m.substring(0,i)+m.substring(i+1,i+2)+"."+m.substring(i+2,m.length());break;}}if(i>m.length()-1)t = m.substring(0,3)+"."+m.substring(3,m.length());return t;}privatestatic String findNext(String m){//返回.后的字母String c = "#";for(int i = 0 ; i<m.length()-1 ; i++){if(m.substring(i,i+1).equals(".")){c= m.substring(i+1,i+2);}}return c;}}ViablePrefixe.javapackage analysis;publicclass ViablePrefixe {//活前缀类private String state = "";//状态private String projectSet = "";//项目private String nextSign = "";//后继符号private String nextState = "";//后继状态public ViablePrefixe(String state,String projectSet,String nextSign,String n extState){this.state = state;this.projectSet = projectSet;this.nextSign = nextSign;this.nextState = nextState;}public ViablePrefixe(String state,String projectSet,String nextSign){ this.state = state;this.projectSet = projectSet;this.nextSign = nextSign;}public ViablePrefixe(String state,String projectSet){this.state = state;this.projectSet = projectSet;}public ViablePrefixe(){}public StringgetState() {return state;}publicvoid setState(String state) {this.state = state;}public StringgetProjectSet() {return projectSet;}publicvoid setProjectSet(String projectSet) {this.projectSet = projectSet;}public StringgetNextSign() {return nextSign;}publicvoid setNextSign(String nextSign) {this.nextSign = nextSign;}public StringgetNextState() {return nextState;}publicvoid setNextState(String nextState) {this.nextState = nextState;}public StringtoString(){return state+" "+projectSet+" "+nextSign+" "+nextState+"\n"; }}三、实验结果。