zl程序教程

您现在的位置是:首页 >  后端

当前栏目

基于Java实现(图形界面)小型类 C 语言编译器【100010634】

JAVA语言编译器 实现 基于 图形界面 小型
2023-09-11 14:17:49 时间

小型类 C 语言编译器

一、设计目的及设计要求

设计一个完整的小的编译程序模型,在 Java 语言为工具的基础上,实现从 C 语言(部分核心语法)到汇编语言的编译,进一步加深理解和掌握所学知识,完成词法分析,语法分析,语义分析和中间代码生成,最终产生目标汇编代码。

二、开发环境描述

操作系统:Windows 10,Intel® Core™ i7-8750H CPU @ 2.20GHz

集成开发环境:eclipse-java-2019-06-R-win32-x86_64

三、设计内容、主要算法描述

对于本部分“设计内容、主要算法描述”,我将分为词法分析、语法分析、中间代码生成、目标代码生成四个主要部分进行介绍(也就是对程序的四个主要功能实现的 Java 类介绍),其中涉及到的其他小类就顺带在大类中介绍。

3.1 词法分析 LexAnalyse

词法分析的定义是根据词法规则识别出源程序中的各个记号(token),每个记号代表一类单词(lexeme)。源程序中常见的记号可以归为几大类:关键字、标识符、字面量和特殊符号。词法分析器的输入是源程序,输出是识别的记号流。词法分析器的任务是把源文件的字符流转换成记号流。本质上它查看连续的字符然后把它们识别为“单词”。

在我设计的编译器中,词法分析的结果将被存于 wordList 的 ArrayList 中,同时将被存于 tiny Compiler 包下的 output 文件夹下的 wordList.txt 文件中。要对词法分析介绍,就得先介绍其中用到的小类 Word 类和 Error 类。

Word 类

单词 Word 类包括四个成员变量:整型变量单词序号 id,字符串变量单词的值 value,字符串变量单词类型 type,整型变量单词所在行 line,布尔型变量单词合法标志 flag(但是构造函数时无需构造,默认为 true),如下表所示:

表 1 Word 类成员变量

数据类型数据名字数据含义
intid单词序号
Stringvalue单词值
Stringtype单词类型
intline单词所在行
booleanflag单词合法标志

声明中的类型有以下多种:KEY(关键词)、OPERATOR(运算符),INT_CONST(整形常量)、CHAR_CONST(字符常量)、BOOL_CONST(布尔常量)、IDENTIFYER(标志符)、BOUNDARYSIGN(界符)、END(结束符)、UNIDEF(未知类型);

其中 KEY 类型包括以下符号:void、main、int、char、if、else、while、for、printf、scanf;其中 OPERATOR 类型包括以下符号:+、-、++、–、*、/、>、<、>=、<=、==、!=、=、&&、||、!、.、?、|、&;其中 BOUNDARYSIGN 类型包括以下符号:(、)、{、}、;、,;

除构造函数外,单词类 Word 还提供了 5 种成员函数如下表所示:(其中最后两种函数是 isOperator 函数的后续分流函数)

表 2 Word 类成员函数

级别函数名字函数功能
1boolean isKey(String word)判断单词 word 是否是关键词
1boolean isOperator(String word)判断单词 word 是否是运算符
1boolean isBoundarySign(String word)判断单词 word 是否是边界符
2boolean isArOP(String word)判断 word 是否是算数运算符
2boolean isBoolOP(String word)判断 word 是否是逻辑运算符

Error 类

错误 Error 类有四个成员变量:整型变量错误序号 id,字符串变量 info 错误信息 info,整型变量错误所在行 line,Word 类对象错误的单词 word。其构造函数就是通过其参数构造一个 Error 类对象,如下表所示:

表 3 Error 类成员变量

数据类型数据名字数据含义
intid错误序号
Stringinfo错误信息
intline错误所在行
Wordword错误的单词对象

LexAnalyse 类

介绍完单词类Word和错误类Error,下面就可以介绍LexAnalyse类了,其由ArrayList单词表wordList(用于顺序存储词法分析得到的每个单词),ArrayList错误信息表errorList,整型变量单词个数wordCount,整型变量errorCount错误个数,布尔类型变量多行注释标志noteFlag,布尔类型变量词法分词错误标志lexErrorFlag,如下表所示:

表 4 LexAnalyse 类成员变量

数据类型或结构名称含义与作用
ArrayListwordlist单词表,存储词法分析出的单词
ArrayListerrorList错误信息表,存储词法分析出的错误信息
intwordcount单词个数,统计
interrorCount错误个数,统计
booleannoteFlag多行注释标志,检测到多行注释时置为 1,排除掉后置为 0
booleanlexErrorFlag词法分析出错标志

除构造函数外,本函数还提供以下成员函数,如下表所示:

表 5 LexAnalyse 类成员函数

函数名字函数作用
boolean isDigit(char ch)判断单个字符 ch 是否为数字
boolean isInteger(String word)判断单词对象 word 的值是否为数字
boolean isLetter(char ch)判断单个字符 ch 是否为字母
boolean isID(String word)判断单词对象 word 的值是否是标识符
boolean isFail()判断词法分析是否出错
void analyse(String str, int line)对 line 行的字符串 str 进行词法分析
ArrayList lexAnalyse(String str)对字符串 str,调用 analyse()函数来进行词法分析,结果存到 wordList
ArrayList lexAnalyse1(String filePath)对 filePath 路径内的文件,调用 analyse()函数来进行词法分析,结果存到 wordList
String outputWordList()把 wordList 中的词法分析结果写到路径下的/output/文件下,并返回这个文件的路径

其中最核心的函数是 void analyse(String str, int line),也就是对 line 行的字符串 str 进行词法分析的具体函数。限于不能大量引用代码进行分析,我将用图片形式进行介绍,如下图 1 所示:

图 1 状态转换图

简单介绍一下上面的状态转换图的思路:

1)首先读取第一个字符,根据第一个字符的判断结果,进行后续操作:

2)如果第一个字符是字母或者下划线,继续判断后面的字符直到出现边界符、运算符、空字符、回车换行符、回车符、制表符才停下,停下后判断读取的 word,是关键字、标识符、或是非法标识符;

3)如果第一个字符是数字,继续判断后面的字符直到出现边界符、运算符、空字符、回车换行符、回车符、制表符才停下,停下后判断读取的 word,是整型常量或是非法标识符;

4)如果第一个字符是单引号’,继续判断后面的字符直到长度超出本行,或是另外一个单引号’,或是某位字符不是 0-255 的 ASCII 码才停下,停下后判断读取的 word,是字符常量或是非法标识符;

5)如果第一个字符是等号=,继续判断紧接着的下一个字符是不是一个=,由此判断运算符=还是运算符==;

6)如果第一个字符是等感叹号!,继续判断紧接着的下一个字符是不是一个=,由此判断运算符!还是运算符!=;

7)如果第一个字符是与符号&,继续判断紧接着的下一个字符是不是一个&,由此判断运算符&还是运算符&&;

8)如果第一个字符是或符号 |,继续判断紧接着的下一个字符是不是一个 |,由此判断运算符 | 还是运算符 ||;

9)如果第一个字符是加号 +,继续判断紧接着的下一个字符是不是一个 +,由此判断运算符 + 还是运算符 ++;

10)如果第一个字符是减号-,继续判断紧接着的下一个字符是不是一个-,由此判断运算符-还是运算符–;

11)如果第一个字符是与符号/,继续判断紧接着的下一个字符是不是一个/,或是一个*,由此判断是单行注释//,还是多行注释/*,还是运算符/;

12)如果以上都不是,就通过 switch 语法判断是否是’ ‘、’\t’、‘\r’、‘\n’、‘[’、‘]’、‘(’、‘)’、‘{’、‘}’、‘,’、‘"’、‘.’、‘;’、‘*’、‘%’、 ‘>’、‘<’、‘?’、‘#’,并按照 Word 中的分类对其进行类型判断,并且存入 wordList

13)如果上述都不是,那么算做非法标识符。

3.2 语法分析 Parser

语法分析器根据语法规则识别出记号流中的结构(短语、句子),并构造一棵能够正确反映该结构的语法树。

在我设计的编译器中,语法分析是最困难的一步,结构最复杂。语法分析涉及到的最主要的预备知识和结构如下:

C 语言的 LL1 语法

为了适当降低难度,我选择的是 LL1 文法,具体文法(没有实现对 C 语言的所有语法,只是子集)如下:

1.1、文法开始:
2.S->voidmain(){A}
3.
4.2、声明:
5.X->YZ;
6.Y->int|char|bool
7.Z->UZ’
8.Z’->,Z|$
9.U->idU’
10.U’->=L|$
11.
12.3、赋值:
13.R->id=L;
14.
15.4、算术运算:
16.L->TL’
17.L’->+L|-L|$
18.T->FT’
19.T’->*T|/T|$
20.F->(L)
21.F->id|num
22.O->++|--|$
23.Q->idO|$
24.
25.5、布尔运算
26.E->HE’
27.E’->&&E|$
28.H->GH’
29.H’->||H
30.H’->$
31.G->FDF
32.D-><|>|==|!=
33.G->(E)
34.G->!E
35.
36.5、控制语句
37.B->if(E){A}else{A}
38.B->while(E){A}
39.B->for(YZ;G;Q){A}
40.
41.6、功能函数
42.B->printf(P);
43.B->scanf(id);
44.P->id|ch|num
45.
46.7、复合语句
47.A->CA
48.C->X|B|R
49.A->$

四元式类 FourElement

四元式 FourElement 类有五个成员变量:整型变量四元式序号 id,字符串变量操作符 op,字符串变量第一个操作数 arg1,字符串变量第二个操作数 arg2,字符串变量结果 result。其构造函数就是通过其参数构造一个 FourElement 类对象,如下表所示:

表 6 FourElement 类成员变量

数据类型数据名字数据含义
intid四元式序号
Stringop四元式操作符
Stringarg1第一个操作数
Stringarg2第二个操作数
Stringresult结果

要进行语法分析,就需要从语法分析器得到的结果 wordList 中不断取出第一个数,与分析栈 analyseStack 之间进行配合分析,必要时将一些数据填入语义栈 semanticStack 和四元式列表 fourElemList。在语法分析这一步,最重要的就是上述四个“数据结构”。大致示意图如下:

图 2 语法分析示意图

LL(1)文法:从文法的开始符,向下推导,推出句子。对文法 G 的句子进行确定的自顶向下语法分析的充分必要条件是,G 的任意两个具有相同左部的产生式 A—>α|β 满足下列条件:

(1)如果 α、β 均不能推导出 ε,则 FIRST(α) ∩ FIRST(β) = 。

(2)α 和 β 至多有一个能推导出 ε。

(3)如果 β *═> ε,则 FIRST(α) ∩ FOLLOW(A) = 。

将满足上述条件的文法称为 LL(1)文法。

实例分析

由于语法分析比较复杂,为了更好的介绍语法分析,我将对实例中的一段 C 语言代码经过词法分析和语法分析的过程进行介绍,如下:

1.voidmain()
2.{
3.intsum=0;
4.for(inti=1;i<11;i++){
5.sum=sum+i;
6.}
7.}
# 

这是我输入的要进行词法分析和语法分析的 C 语言代码段(限制代码段不能超过 10 行,所以不取太多)。

首先是词法分析,根据我们之前介绍的词法分析,编译器中的词法分析器,将会对每一行进行分析,提取出所有的单词 word 存入 wordList,最终结果是 44 个单词(含结束符#),也就是说单词表 wordList 结果如下:

1.单词序号单词的值单词类型单词所在行单词是否合法
2.1void 关键字1true
3.2main关键字1true
4.3(界符1true
5.4)界符1true
6.5{界符2true
7.6int关键字3true
8.7sum标志符3true
9.8=运算符3true
10.90整形常量3true
11.10;界符3true
12.11for关键字4true
13.12(界符4true
14.13int关键字4true
15.14i标志符4true
16.15=运算符4true
17.161整形常量4true
18.17;界符4true
19.18i标志符4true
20.19<运算符4true
21.2011整形常量4true
22.21;界符4true
23.22i标志符4true
24.23++运算符4true
25.24)界符4true
26.25{界符4true
27.26sum标志符5true
28.27=运算符5true
29.28sum标志符5true
30.29+运算符5true
31.30i标志符5true
32.31;界符5true
33.32}界符6true
34.33}界符7true
35.34#结束符8true
36.词法分析通过:

语法分析:

首先需要在语法分析栈中放入文法开始符和结束符 S#,在语义栈中放入#。然后开始语法分析:

步骤 1)

S 被读取,根据程序,在下一步中,voidmain(){A}#将被存入语法分析栈;

步骤 2)

当前语法分析栈:voidmain(){A}#

wordList 中:voidmain(){intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:#

步骤 3)

可以看出此时 term.equals(firstWord.value),所以可以将语法分析栈和 wordList 的栈顶元素相抵消,并且接下来几个都可以抵消,直到如下状态:

当前语法分析栈:A}#

wordList 中:intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:#

此时根据文法,应该使用 A->C,结果如下一步骤

步骤 4)

当前语法分析栈:CA}#

wordList:intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:#

此后都是按照文法,判断,进入不同的路径即可,直到第一个赋值语句;

步骤 5)

由于前面的已经列出的文法的判断帮助,文法将声明语句帮助我们识别赋值:

1.X->YZ;
2.Y->int|char|bool
3.Z->UZ’
4.Z’->,Z|$
5.U->idU’
6.U’->=L|$

重点在于报告中要求“基于一遍扫描的语法制导翻译方法。算术表达式、 赋值语句、布尔表达式、控制语句等语法单位的翻译模式。”

所以对于之前已经提到的文法,我们需要构造 LL1 属性翻译文法,即在原有 LL1 文法基础上加上动作符号,并给非终结符和终结符加上一定属性,给动作符号加上语义子程序,具体改动如下:

2.1、构造LL1属性翻译文法
3.构造LL1属性翻译文法即在原有LL1文法基础上加上动作符号,并给非终结符和终结符加上一定属性,给动作符号加上语义子程序。
4.对原有LL1文法改进的地方如下:
5.1、赋值:
6.产生式语义子程序
7.R->@ASS_Rid=L@EQ;@ASS{R.VAL=id并压入语义栈}
8.@EQ{RES=R.VAL,OP=’=’,ARG1=L.VAL,
9.newfourElement(OP,ARG1,/,RES)}
10.U->@ASS_UidU’{U.VAL=id并压入语义栈}
11.U’->=L|$@EQ_U’{RES=U.VAL,OP=’=’,ARG1=L.VAL,newfourElement(OP,ARG1,/,RES)}
12.
13.2、算术运算:
14.产生式语义子程序
15.L->TL’@ADD_SUB{If(OP!=null)RES=NEWTEMP;L.VAL=RES,并压入语义栈;NewfourElement(OP,T.VAL;,L’VAL,RES),
16.}
17.L’->+L@ADD{OP=+,ARG2=L.VAL}
18.L’->-L@SUB{OP=-,ARG2=L.VAL}
19.L’->$
20.T->FT’@DIV_MUL{if(OP!=null)RES=NEWTEMP;T.VAL=RES;
21.newFourElement(OP,F.VAL,ARG2,RES)
22.elseARG1=F.VAL;}
23.T’->/T@DIV{OP=/,ARG2=T.VAL}
24.T’->*T@MUL{OP=*,ARG2=T.VAL}
25.T’->$
26.F->(L)@VOL{F.VAL->L.VAL}
27.F->@ASS_Fnum|id{F.VAL=num|id}
28.Q->idO|$
29.O->@SINGLE_OP++|--{OP=++|--}
30.
31.3、布尔运算
32.产生式语义子程序
33.G->FDF@COMPARE{OP=D.VAL;ARG1=F(1).VAL;ARG2=F(2).VAL,RES=NEWTEMP;
34.NewfourElement(OP,F.VAL,ARG2,RES);G.VAL=RES并压入语义栈}
35.D->@COMPARE_OP<|>|==|!={D.VAL=<|>|==|!=,并压入语栈}
36.
37.4、控制语句
38.产生式语义子程序
39.B->if(G)@IF_FJ{A}@IF_BACKPATCH_FJ@IF_RJelse{A}@IF_BACKPATCH_RJ
40.@IF_FJ{OP=”FJ”;ARG1=G.VAL;RES=if_fj,NewfourElement(OP,ARG1,/,RES),将其插入到四元式列表中第i个}
41.@IF_BACKPATCH_FJ{回填前面假出口跳转四元式的跳转序号,BACKPATCH(i,if_fj)}
42.B->while(G)@WHILE_FJ{A}@WHILE_RJ@WHILE_BACKPATCH_FJ{参照ifelse}
43.B->for(YZ;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJ{参照ifelse}
44.@SINGLE{ARG1=id;RES=NEWTEMP;NewfourElement(OP,ARG1,/,RES)}
45.
46.说明:
47.(1)、R.VAL表示符号R的值,VAL是R的一个属性,其它类似。
48.(2)、NEWTEMP()函数:每调用一次生成一个临时变量,依次为T1,T2,…Tn。
49.(3)、BACKPATCH(inti,intres):回填函数,用res回填第i个四元式的跳转地址。
50.(4)、newfourElement(StringOP,StringARG1,StringARG2,StringRES):生成一个四元式
(OP,ARG1,ARG2,RES)

于是在遇到赋值、算数运算、布尔运算、控制语句,到达可以被属性翻译文法处理时,就遵照改进后的 LL1 属性翻译文法进行,也就是它的优先级更高,步骤如下:

步骤 6)

直到各栈等状态如下:

当前语法分析栈:UZ’;BRA}#

wordList:sum=0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:#

于是根据优先级更高的属性翻译文法,翻译后如下步骤:

步骤 7)

当前语法分析栈:@ASS_UidU’Z’;BRA}#

wordList:sum=0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:#

这个@ASS_U 的作用是将要赋值的对象拷入语义栈,然后删除语法分析栈中的@ASS_U,对 wordList 无影响,运行后各栈状态如下一步骤:

步骤 8)

当前语法分析栈:idU’Z’;BRA}#

wordList:sum=0;for(inti=1;i<11;i++){sum=sum+i;}}

#语义栈:sum#

可以看到 sum 拷入语义栈

步骤 9)

上一步之后,语法分析栈中剩余的是 id,它的作用是与 wordList 中的标识符相抵消,于是处理后如下一步:

步骤 10)

当前语法分析栈:U’Z’;BRA}#

余留符号串:=0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:sum#

此时 U’将由属性翻译文法变为下一步骤所示;

步骤 11)

当前语法分析栈:=L@EQ_U’Z’;BRA}#

余留符号串:=0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:sum#

很明显,等号将抵消,但是为保险起见,将语法分析栈中 L 的翻译文法,判断这个等号之前是否存在加减乘除号,如下:

步骤 12)

当前语法分析栈:TL’@ADD_SUB@EQ_U’Z’;BRA}#

余留符号串:0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:sum#

这里是用于判断有无加减号的,然后下一步:

步骤 13)

当前语法分析栈:FT’@DIV_MULL’@ADD_SUB@EQ_U’Z’;BRA}#

wordList:0;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:sum#

这里添加上了判断是否有乘除号。

为了存储要赋值给标识符的值,F 将转化为 F->@ASS_Fnum,如下:

步骤 14)

然后上一步中 wordList 中的 0 将被存入语义栈,num 与 wordList 中的数字 0 抵消,然后到下一步:

步骤 15)

语法分析栈:T’@DIV_MULL’@ADD_SUB@EQ_U’Z’;BRA}#

wordList:;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:0sum#

此时的状态中,T’将被用于判断是否有乘除,若无,T’和@DIV_MULL 都将失效,然后进入下一步骤:

步骤 16)

语法分析栈:L’@ADD_SUB@EQ_U’Z’;BRA}#

余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:0sum#

这一步中,L’将被用于判断是否有加减,若无,L’和@ADD_SUB 都将失效,然后进入下一步骤:

步骤 17)

语法分析栈:@EQ_U’Z’;BRA}#

余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:0sum#

此时就可以确保无误(由于是赋值语句不是判断等语句,所以只需要判断等号前面有无加减乘除即可),下一步将将这个赋值语句生成为四元式。

步骤 18)

当前语法分析栈:@EQ_U’Z’;BRA}#

wordList:;for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:0sum#

在此状态时,将生成四元式,其中操作符是等号,第一操作数是语义栈中的当前栈顶数 0,并出栈,结果是语义栈中的当前栈顶数 sum。四元式生成完毕后,将被存入四元式集合中。此后,将一直简单判断直到 wordList 栈顶为 for

步骤 19)

此时,由于 wordList 栈顶是 for,

根据文法 B->for(YZ;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJ

将进入如下状态:

语法分析栈:for(YZ;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#

余留符号串:for(inti=1;i<11;i++){sum=sum+i;}}#

语义栈:#

这个针对 for 的属性翻译文法是有讲究的,可以看出

for(YZ;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}

YZ 是之前用过的赋值语句,没什么好分析的,我们直接开始分析后面,状态如下:

步骤 20)

步骤当前语法分析栈:G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#

wordList:i<11;i++){sum=sum+i;}}#

语义栈:#

根据文法,唯一一种路径只能:G->FDF@COMPARE

然后进行下一步:

步骤 21)

分析栈:FDF@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#

wordList:i<11;i++){sum=sum+i;}}#

语义栈:#

根据文法,由于此时 wordList 的栈顶是 i(标识符),所以下一步:

步骤 22)

栈:@ASS_FidDF@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#wordList:i<11;i++){sum=sum+i;}}# 、

语义栈:#

于是和之前一样,ASS_F 用于将标识符 i 加入到语义栈,id 用于和 wordList 中的 i 相抵消,然后就是 D,D 是一个双目运算符的文法符号,用于判断==,!=,>,<。所以检测到 wordList 中是 <,将通过文法:D->@COMPARE_OP<;

步骤 23)

语法分析栈:@COMPARE_OP<F@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ

@FOR_BACKPATCH_FJRA}#

余留符号串:<11;i++){sum=sum+i;}}#

语义栈:i#

此时的@COMPARE_OP 将用于把 < 入到语义栈,然后 < 相抵消,之后的 F 将用于读取数字 num1 到生成四元式,如下一步:

步骤 24)

语法分析栈:@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}# wordList:;i++){sum=sum+i;}}#

语义栈:11<i#

到这一步时,语法分析栈中的@COMPARE 将用于生成一个四元式,其中操作数 2 是语义栈栈顶的 11 并将其出栈,操作符是语义栈栈顶的 < 并将其出栈,操作数 1 是语义栈栈顶的 i,然后四元式的结果 result 是通过 newTemp()函数新建的一个字符串“T”+tempCount(初始为 0++);然后将这个四元式存入 fourElemList,然后在语义栈中存入 result。如下一步:

步骤 25)

当前语法分析栈:@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#

余留符号串:;i++){sum=sum+i;}}#

语义栈:T1#

此时,语法分析栈栈顶是@FOR_FJ,其作用是将上一步存入语义栈的 T1 拿出生成一个四元式:(FJ,T1,/,9),然后将之后的两个;相抵消,还有重要的作用就是将这一步生成的四元式的序号存入 Stack for_fj 也就是跳转地址栈,进入下一步:

步骤 26)

当前语法分析栈:Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#

wordList:i++){sum=sum+i;}}#

语义栈:#

这个 Q 也是文法中单独设计的,因为我们知道在 C 语言中,for 语句的一般情况下语法是 for(赋值;判断;递增递减)(没有设计更复杂的),所以 Q 将用于识别这个递增递减部分,如下一步:

步骤 27)

当前语法分析栈:@ASS_QidO){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#

余留符号串:i++){sum=sum+i;}}#

语义栈:#

可以看出,@ASS_Q 用于读取 i 到语义栈,id 用于和 i 相抵消,O 用于识别递增递减符号,其中 O 生成的@SINGLE_OP 用于将 ++ 或是—存入 Stackfor_op,后面在 SINGLE 时,再将其取出这三个 top 识别完成后,状态如下一步(不需要存入四元式,因为 for 循环中的递增不是在这个时候进行,而是在循环完成一轮时进行):

步骤 28)

当前语法分析栈:{A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#

余留符号串:{sum=sum+i;}}#

语义栈:i#

A 就不必多说了,是用于读取 sum = sum + i,唯一需要注意的是这种赋值语句,不论是自身赋值 a = a + b,还是 a = b + c,都是只需要两个四元式就可以完成,之前在 i = 1 已经使用过了。那么@SINGLE 在前面的介绍中我们也知道是用于读取之前读到 for_op 中的递增或是递减符号,如下一步。

步骤 29)

当前语法分析栈:@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#

余留符号串:}}#

语义栈:i#

这一步就完成了 i++ 的四元式化,下一步就进入到 for 循环的收尾阶段。

步骤 30)

当前语法分析栈:@FOR_RJ@FOR_BACKPATCH_FJRA}#

余留符号串:}#

语义栈:#

这里的@FOR_RJ 和@FOR_BACKPATCH_FJRA 都是为了循环完成后的回溯准备的,思路如下:

}else if(top.name.equals("@FOR_RJ")){  
    OP="RJ";  
    RES=(for_fj.peek()-1)+"";  
    FourElement fourElem=new FourElement(++fourElemCount,OP,"/","/",RES);  
    for_rj.push(fourElemCount);  
    fourElemList.add(fourElem);  
    OP=null;  
    analyseStack.remove(0);  
}else if(top.name.equals("@FOR_BACKPATCH_FJ")){  
    backpatch(for_fj.pop(), fourElemCount+1);  
    analyseStack.remove(0);  
}  

*可以看出,@FOR_RJ 是用于生成四元式**(RJ,/,/,3)**的,这个 3 就来自于之前跳转地址栈 for_fj 栈存入的 for 语句判断语句存入的四元式的序号 3,但是并不出栈找这个数字 3,因为后面的@FOR_BACKPATCH 还要用到。存入了当前四元式的序号到地址栈\Stack for_rj*中,目的是为了退出循环,也是后面的@FOR_BACKPATCH 还要用到。\

步骤 31)

当前语法分析栈:@FOR_BACKPATCH_FJRA}#

余留符号串:}#

语义栈:#

根据上面的 12 行代码可知,对参数调用了 backpatch 函数,这个函数定义如下:

private void backpatch( int i, int res )
{
	  
	FourElement temp	= fourElemList.get( i - 1 );   
	temp.	result	= res + "";   
	fourElemList.set( i - 1,  temp );   
}   

作用很明显,就是将 for 循环的最后一个四元式序号 +1(也就是退出 for 循环后的位置)作为参数,然后其传回到 for 循环的判断开始处,更新之前的判断四元式的 result,意即当那个判断为否时,就直接退出 for 循环,来到 for 循环的下一行(退出循环)。

以上就是本语法分析器的主要作用,本报告以一个 11 行的 C 语言代码(包含赋值语句、判断语句、递减)的词法分析、语法分析、中间代码生成(四元式)的例子来进行功能、设计思想上的介绍。

语法分析中已经生成的中间代码将用于在下一步中进行目标代码(汇编语言)的生成。

3.3 目标代码生成 huibian

中间代码生成器根据语义分析器的输出生成中间代码。中间代码可以有若干种形式,它们的共同特征是与具体机器无关。最常用的一种中间代码是三地址码,它的一种实现方式是四元式,在上一部分的语法分析中,我得到的中间代码结果,也就是四元式,如下:

1.生成的四元式如下
2.序号(OP,ARG1,ARG2,RESULT)
3.1(=,0,/,sum)
4.2(=,1,/,i)
5.3(<,i,11,T1)
6.4(FJ,T1,/,9)
7.5(+,sum,i,T2)
8.6(=,T2,/,sum)
9.7(++,i,/,i)
10.8(RJ,/,/,3)

目标代码生成是编译器的最后一个阶段。在生成目标代码时要考虑以下几个问题:计算机的系统结构、指令系统、寄存器的分配以及内存的组织等。编译器生成的目标程序代码可以有多种形式:汇编语言、可重定位二进制代码、内存形式。这一步其实难度不大,有了四元式,想要生成目标代码就是简单的循环判断即可。

在验收的时候。蒋老师对我的工作给出了很高的评价,同时也指出更好的编译器最后一步汇编代码生成,应该是使用单词表,而不是使用逻辑循环来翻译。

如对上述的四元式结果,我们继续实例分析:

实例分析

步骤 1)

按照换行符进行分行,从第三行开始处理,通过逗号,进行分词,首先读取第一个逗号前的符号,如果是=,那么就判断为赋值语句,配合四元式,产生目标汇编代码为:MOV sum,0

步骤 2)

仍旧是=,赋值语句,目标代码生成为:MOV i,1

步骤 3)

四元式首个符号为 <,比较语句,目标代码生成为:CMP i,11

步骤 4)

四元式首个符号为 F,下一个符号为 J,目标代码生成为:JZ 11

(我是按照大二时学习的 8086 汇编代码来设计的,这两行代码的意思也就是比较 i 和 11,如果 11 小于 i,Less(JL)就跳转到四元式中序号 9 的位置去)

步骤 5)

四元式首个符号为 +,运算符,目标代码生成为:MOV AX,i、MOV T2,sum、ADD T2,AX

步骤 6)

四元式首个符号为=,赋值语句,目标代码生成为:MOV sum,T2

步骤 7)

四元式首个符号为 ++,递增语句,目标代码生成为:INC i

步骤 8)

四元式首个符号为 RJ,for 的回溯,目标代码生成为:JMP 3

最后目标代码结果如下:

1.生成的目标代码如下
2.序号(OP,ARG1,ARG2)
3.1MOVsum,0
4.2MOVi,1
5.3CMPi,11
6.4JL11
7.5MOVAX,i
8.6MOVT2,sum
9.7ADDT2,AX
10.8MOVsum,T2
11.9INCi
12.10JMP3

3.4 演示界面设计

演示代码的设计,由两个类组成:

主界面 MainFrame

主界面上设置三个 Panel,布局都是 BorderLayout。

然后在布局 North 加入组件 createUpPane,其中放入一些界面显示文字的控件,最主要的是浏览和确认按钮,其浏览按钮的动作函数是打开文件夹选择文件,确认按钮的动作函数是打开文件内容并且读取,然后显示在 textArea 上。

在布局 Center 加入组件 createCenterPane,其中放入一些界面显示文字的控件,最主要的是一个显示 textArea 控件,用于显示从文件中读取的源代码文件。

在布局 COUTH 加入组件 createBottomPane,其中放入四个按钮控件,分别唤醒四个子界面 InfoFeame,分别显示词法分析,语法分析,中间代码生成,目标代码生成。

子界面 InfoFrame

显示一个有 title 的子界面,将每一步(词法分析、语法分析、中间代码生成、目标代码生成)的存入路径下的结果拿出,显示到子界面的 TextArea 中。

四、设计的输入和输出形式

输入内容是一个 C 语言源代码文件 a.c,如下所示:

图 3 源代码在文件夹中的形式

内容如下,其形式是一个完整的 C 语言源代码加上一个结束符#

图 4 被编译的 C 语言源代码

输出内容是在路径/output/下的三个文件 wordList.txt,用于存储词法分析结果;LL1.txt,用于存储语法分析结果;FourElement.txt,用于存储四元式分析结果(中间代码)。

词法分析结果 wordList.txt 如下,其形式是五列数据,其内容分别是:单词序号、单词的值、单词类型、单词所在行、单词是否合法。

图 5 词法分析结果文件

语法分析结果 LL1.txt 如下,其形式是:步骤及序号、当前语法分析栈的内容(对应文法)、余留符号串(也就是 wordList 中的单词集合)、语义栈(用于生成

四元式)。

图 6 语法分析结果文件

四元式分析结果 FourElement.txt 如下,其形式是:四元式序号、四元式操作符、四元式操作数 1、四元式操作数 2、四元式结果。

五、程序运行的结果

为了充分展示设计到的 C 语言语法,此处我们选择一个相对较为复杂,包含赋值,循环,判断,递增,四则运算等的的源代码作为输入,也就是 a.c,作为我的程序运行测试的样例。运行程序,初始界面如下:

图 8 程序运行初始界面

点击“浏览…”按钮,可以选择要编译的 C 语言文件,界面如下:

图 9 打开文件夹选择.c 文件功能界面

选择好之后源代码文件 b.c 之后,该文件路径将显示在 text 中。

图 10 选择好.c 文件后界面

然后点击按钮“确定”,就可以将文件显示在下面的 textArea 中,如下所示:

图 11 源程序展示界面

然后点击“词法分析”按钮,就会弹出子界面,里面是词法分析的结果:

图 12 词法分析结果界面

然后点击“语法分析”按钮,就会弹出子界面,里面是语法分析的结果:

图 13 语法分析结果界面

然后点击“中间代码生成”按钮,就会弹出子界面,里面是四元式分析结果:

图 14 中间代码四元式分析结果界面

然后点击目标代码生成,就会弹出子界面,里面是目标代码(汇编语言):

图 15 目标代码生成

界面

至此,所有界面都已展示完毕,下面安装课设要求,拷贝结果的打印输出:

源文件 a.c:

1.voidmain()
2.{
3.intsum=0;
4.for(inti=1;i<11;i++){
5.sum=sum+i;
6.}
7.}
8.#

词法分析结果:

1.单词序号单词的值单词类型单词所在行单词是否合法
2.1void关键字1true
3.2main关键字1true
4.3(界符1true
5.4)界符1true
6.5{界符2true
7.6int关键字3true
8.7sum标志符3true
9.8=运算符3true
10.90整形常量3true
11.10;界符3true
12.11for关键字4true
13.12(界符4true
14.13int关键字4true
15.14i标志符4true
16.15=运算符4true
17.161整形常量4true
18.17;界符4true
19.18i标志符4true
20.19<运算符4true
21.2011整形常量4true
22.21;界符4true
23.22i标志符4true
24.23++运算符4true
25.24)界符4true
26.25{界符4true
27.26sum标志符5true
28.27=运算符5true
29.28sum标志符5true
30.29+运算符5true
31.30i标志符5true
32.31;界符5true
33.32}界符6true
34.33}界符7true
35.34#结束符8true
36.词法分析通过:

语法分析结果:

1.步骤0当前语法分析栈:voidmain(){A}#余留符号串:voidmain(){intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
2.步骤1当前语法分析栈:main(){A}#余留符号串:main(){intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
3.步骤2当前语法分析栈:(){A}#余留符号串:(){intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
4.步骤3当前语法分析栈:){A}#余留符号串:){intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
5.步骤4当前语法分析栈:{A}#余留符号串:{intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
6.步骤5当前语法分析栈:A}#余留符号串:intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
7.步骤6当前语法分析栈:CA}#余留符号串:intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
8.步骤7当前语法分析栈:XBRA}#余留符号串:intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
9.步骤8当前语法分析栈:YZ;BRA}#余留符号串:intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
10.步骤9当前语法分析栈:intZ;BRA}#余留符号串:intsum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
11.步骤10当前语法分析栈:Z;BRA}#余留符号串:sum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
12.步骤11当前语法分析栈:UZ';BRA}#余留符号串:sum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
13.步骤12当前语法分析栈:@ASS_UidU'Z';BRA}#余留符号串:sum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
14.步骤13当前语法分析栈:idU'Z';BRA}#余留符号串:sum=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:sum#
15.步骤14当前语法分析栈:U'Z';BRA}#余留符号串:=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:sum#
16.步骤15当前语法分析栈:=L@EQ_U'Z';BRA}#余留符号串:=0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:sum#
17.步骤16当前语法分析栈:L@EQ_U'Z';BRA}#余留符号串:0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:sum#
18.步骤17当前语法分析栈:TL'@ADD_SUB@EQ_U'Z';BRA}#余留符号串:0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:sum#
19.步骤18当前语法分析栈:FT'@DIV_MULL'@ADD_SUB@EQ_U'Z';BRA}#余留符号串:0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:sum#
20.步骤19当前语法分析栈:@ASS_FnumT'@DIV_MULL'@ADD_SUB@EQ_U'Z';BRA}#余留符号串:0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:sum#
21.步骤20当前语法分析栈:numT'@DIV_MULL'@ADD_SUB@EQ_U'Z';BRA}#余留符号串:0;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:0sum#
22.步骤21当前语法分析栈:T'@DIV_MULL'@ADD_SUB@EQ_U'Z';BRA}#余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:0sum#
23.步骤22当前语法分析栈:@DIV_MULL'@ADD_SUB@EQ_U'Z';BRA}#余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:0sum#
24.步骤23当前语法分析栈:L'@ADD_SUB@EQ_U'Z';BRA}#余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:0sum#
25.步骤24当前语法分析栈:@ADD_SUB@EQ_U'Z';BRA}#余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:0sum#
26.步骤25当前语法分析栈:@EQ_U'Z';BRA}#余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:0sum#
27.步骤26当前语法分析栈:Z';BRA}#余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
28.步骤27当前语法分析栈:;BRA}#余留符号串:;for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
29.步骤28当前语法分析栈:BRA}#余留符号串:for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
30.步骤29当前语法分析栈:for(YZ;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:for(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
31.步骤30当前语法分析栈:(YZ;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:(inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
32.步骤31当前语法分析栈:YZ;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
33.步骤32当前语法分析栈:intZ;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:inti=1;i<11;i++){sum=sum+i;}}#语义栈:#
34.步骤33当前语法分析栈:Z;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i=1;i<11;i++){sum=sum+i;}}#语义栈:#
35.步骤34当前语法分析栈:UZ';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i=1;i<11;i++){sum=sum+i;}}#语义栈:#
36.步骤35当前语法分析栈:@ASS_UidU'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i=1;i<11;i++){sum=sum+i;}}#语义栈:#
37.步骤36当前语法分析栈:idU'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i=1;i<11;i++){sum=sum+i;}}#语义栈:i#
38.步骤37当前语法分析栈:U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:=1;i<11;i++){sum=sum+i;}}#语义栈:i#
39.步骤38当前语法分析栈:=L@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:=1;i<11;i++){sum=sum+i;}}#语义栈:i#
40.步骤39当前语法分析栈:L@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:1;i<11;i++){sum=sum+i;}}#语义栈:i#
41.步骤40当前语法分析栈:TL'@ADD_SUB@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:1;i<11;i++){sum=sum+i;}}#语义栈:i#
42.步骤41当前语法分析栈:FT'@DIV_MULL'@ADD_SUB@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:1;i<11;i++){sum=sum+i;}}#语义栈:i#
43.步骤42当前语法分析栈:@ASS_FnumT'@DIV_MULL'@ADD_SUB@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:1;i<11;i++){sum=sum+i;}}#语义栈:i#
44.步骤43当前语法分析栈:numT'@DIV_MULL'@ADD_SUB@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:1;i<11;i++){sum=sum+i;}}#语义栈:1i#
45.步骤44当前语法分析栈:T'@DIV_MULL'@ADD_SUB@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i<11;i++){sum=sum+i;}}#语义栈:1i#
46.步骤45当前语法分析栈:@DIV_MULL'@ADD_SUB@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i<11;i++){sum=sum+i;}}#语义栈:1i#
47.步骤46当前语法分析栈:L'@ADD_SUB@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i<11;i++){sum=sum+i;}}#语义栈:1i#
48.步骤47当前语法分析栈:@ADD_SUB@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i<11;i++){sum=sum+i;}}#语义栈:1i#
49.步骤48当前语法分析栈:@EQ_U'Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i<11;i++){sum=sum+i;}}#语义栈:1i#
50.步骤49当前语法分析栈:Z';G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i<11;i++){sum=sum+i;}}#语义栈:#
51.步骤50当前语法分析栈:;G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i<11;i++){sum=sum+i;}}#语义栈:#
52.步骤51当前语法分析栈:G@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i<11;i++){sum=sum+i;}}#语义栈:#
53.步骤52当前语法分析栈:FDF@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i<11;i++){sum=sum+i;}}#语义栈:#
54.步骤53当前语法分析栈:@ASS_FidDF@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i<11;i++){sum=sum+i;}}#语义栈:#
55.步骤54当前语法分析栈:idDF@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i<11;i++){sum=sum+i;}}#语义栈:i#
56.步骤55当前语法分析栈:DF@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:<11;i++){sum=sum+i;}}#语义栈:i#
57.步骤56当前语法分析栈:@COMPARE_OP<F@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:<11;i++){sum=sum+i;}}#语义栈:i#
58.步骤57当前语法分析栈:<F@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:<11;i++){sum=sum+i;}}#语义栈:<i#
59.步骤58当前语法分析栈:F@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:11;i++){sum=sum+i;}}#语义栈:<i#
60.步骤59当前语法分析栈:@ASS_Fnum@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:11;i++){sum=sum+i;}}#语义栈:<i#
61.步骤60当前语法分析栈:num@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:11;i++){sum=sum+i;}}#语义栈:11<i#
62.步骤61当前语法分析栈:@COMPARE@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i++){sum=sum+i;}}#语义栈:11<i#
63.步骤62当前语法分析栈:@FOR_FJ;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i++){sum=sum+i;}}#语义栈:T1#
64.步骤63当前语法分析栈:;Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;i++){sum=sum+i;}}#语义栈:#
65.步骤64当前语法分析栈:Q){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i++){sum=sum+i;}}#语义栈:#
66.步骤65当前语法分析栈:@ASS_QidO){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i++){sum=sum+i;}}#语义栈:#
67.步骤66当前语法分析栈:idO){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i++){sum=sum+i;}}#语义栈:i#
68.步骤67当前语法分析栈:O){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:++){sum=sum+i;}}#语义栈:i#
69.步骤68当前语法分析栈:@SINGLE_OP++){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:++){sum=sum+i;}}#语义栈:i#
70.步骤69当前语法分析栈:++){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:++){sum=sum+i;}}#语义栈:i#
71.步骤70当前语法分析栈:){A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:){sum=sum+i;}}#语义栈:i#
72.步骤71当前语法分析栈:{A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:{sum=sum+i;}}#语义栈:i#
73.步骤72当前语法分析栈:A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum=sum+i;}}#语义栈:i#
74.步骤73当前语法分析栈:CA@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum=sum+i;}}#语义栈:i#
75.步骤74当前语法分析栈:XBRA@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum=sum+i;}}#语义栈:i#
76.步骤75当前语法分析栈:BRA@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum=sum+i;}}#语义栈:i#
77.步骤76当前语法分析栈:RA@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum=sum+i;}}#语义栈:i#
78.步骤77当前语法分析栈:@ASS_Rid=L@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum=sum+i;}}#语义栈:i#
79.步骤78当前语法分析栈:id=L@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum=sum+i;}}#语义栈:sumi#
80.步骤79当前语法分析栈:=L@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:=sum+i;}}#语义栈:sumi#
81.步骤80当前语法分析栈:L@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum+i;}}#语义栈:sumi#
82.步骤81当前语法分析栈:TL'@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum+i;}}#语义栈:sumi#
83.步骤82当前语法分析栈:FT'@DIV_MULL'@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum+i;}}#语义栈:sumi#
84.步骤83当前语法分析栈:@ASS_FidT'@DIV_MULL'@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum+i;}}#语义栈:sumi#
85.步骤84当前语法分析栈:idT'@DIV_MULL'@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:sum+i;}}#语义栈:sumsumi#
86.步骤85当前语法分析栈:T'@DIV_MULL'@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:+i;}}#语义栈:sumsumi#
87.步骤86当前语法分析栈:@DIV_MULL'@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:+i;}}#语义栈:sumsumi#
88.步骤87当前语法分析栈:L'@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:+i;}}#语义栈:sumsumi#
89.步骤88当前语法分析栈:+L@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:+i;}}#语义栈:sumsumi#
90.步骤89当前语法分析栈:L@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i;}}#语义栈:sumsumi#
91.步骤90当前语法分析栈:TL'@ADD_SUB@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i;}}#语义栈:sumsumi#
92.步骤91当前语法分析栈:FT'@DIV_MULL'@ADD_SUB@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i;}}#语义栈:sumsumi#
93.步骤92当前语法分析栈:@ASS_FidT'@DIV_MULL'@ADD_SUB@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i;}}#语义栈:sumsumi#
94.步骤93当前语法分析栈:idT'@DIV_MULL'@ADD_SUB@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:i;}}#语义栈:isumsumi#
95.步骤94当前语法分析栈:T'@DIV_MULL'@ADD_SUB@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;}}#语义栈:isumsumi#
96.步骤95当前语法分析栈:@DIV_MULL'@ADD_SUB@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;}}#语义栈:isumsumi#
97.步骤96当前语法分析栈:L'@ADD_SUB@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;}}#语义栈:isumsumi#
98.步骤97当前语法分析栈:@ADD_SUB@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;}}#语义栈:isumsumi#
99.步骤98当前语法分析栈:@ADD@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;}}#语义栈:isumsumi#
100.步骤99当前语法分析栈:@ADD_SUB@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;}}#语义栈:isumsumi#
101.步骤100当前语法分析栈:@EQ;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;}}#语义栈:T2sumi#
102.步骤101当前语法分析栈:;A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:;}}#语义栈:i#
103.步骤102当前语法分析栈:A@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:}}#语义栈:i#
104.步骤103当前语法分析栈:@SINGLE}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:}}#语义栈:i#
105.步骤104当前语法分析栈:}@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:}}#语义栈:#
106.步骤105当前语法分析栈:@FOR_RJ@FOR_BACKPATCH_FJRA}#余留符号串:}#语义栈:#
107.步骤106当前语法分析栈:@FOR_BACKPATCH_FJRA}#余留符号串:}#语义栈:#
108.步骤107当前语法分析栈:RA}#余留符号串:}#语义栈:#
109.步骤108当前语法分析栈:A}#余留符号串:}#语义栈:#
110.步骤109当前语法分析栈:}#余留符号串:}#语义栈:#
111.步骤110当前语法分析栈:#余留符号串:#语义栈:#
112.步骤111
113.当前语法分析栈:余留符号串:语义栈:#
114.语法分析通过:

中间代码生成结果:

1.生成的四元式如下
2.序号(OP,ARG1,ARG2,RESULT)
3.1(=,0,/,sum)
4.2(=,1,/,i)
5.3(<,i,11,T1)
6.4(FJ,T1,/,9)
7.5(+,sum,i,T2)
8.6(=,T2,/,sum)
9.7(++,i,/,i)
10.8(RJ,/,/,3)

目标代码生成结果:

1.生成的目标代码如下
2.序号(OP,ARG1,ARG2)
3.1MOVsum,0
4.2MOVi,1
5.3CMPi,11
6.4JL11
7.5MOVAX,i
8.6MOVT2,sum
9.7ADDT2,AX
10.8MOVsum,T2
11.9INCi
12.10JMP3

源程序清单

Word.java

package compiler;

import java.util.ArrayList;

import compiler.LexAnalyse;

/**
 * 单词类
 * 
 * @author Administrator 1、单词序号 2、单词的值 3、单词类型 4、单词所在行 5、单词是否合法
 */
public class Word {
	public final static String KEY = "关键字";
	public final static String OPERATOR = "运算符";
	public final static String INT_CONST = "整形常量";
	public final static String CHAR_CONST = "字符常量";
	public final static String BOOL_CONST = "布尔常量";
	public final static String IDENTIFIER = "标志符";
	public final static String BOUNDARYSIGN = "界符";
	public final static String END = "结束符";
	public final static String UNIDEF = "未知类型";
	public static ArrayList<String> key = new ArrayList<String>();// 关键字集合
	public static ArrayList<String> boundarySign = new ArrayList<String>();// 界符集合
	public static ArrayList<String> operator = new ArrayList<String>();// 运算符集合
	static {
		Word.operator.add("+");
		Word.operator.add("-");
		Word.operator.add("++");
		Word.operator.add("--");
		Word.operator.add("*");
		Word.operator.add("/");
		Word.operator.add(">");
		Word.operator.add("<");
		Word.operator.add(">=");
		Word.operator.add("<=");
		Word.operator.add("==");
		Word.operator.add("!=");
		Word.operator.add("=");
		Word.operator.add("&&");
		Word.operator.add("||");
		Word.operator.add("!");
		Word.operator.add(".");
		Word.operator.add("?");
		Word.operator.add("|");
		Word.operator.add("&");
		Word.boundarySign.add("(");
		Word.boundarySign.add(")");
		Word.boundarySign.add("{");
		Word.boundarySign.add("}");
		Word.boundarySign.add(";");
		Word.boundarySign.add(",");
		Word.key.add("void");
		Word.key.add("main");
		Word.key.add("int");
		Word.key.add("char");
		Word.key.add("if");
		Word.key.add("else");
		Word.key.add("while");
		Word.key.add("for");
		Word.key.add("printf");
		Word.key.add("scanf");
	}
	int id;// 单词序号
	String value;// 单词的值
	String type;// 单词类型
	int line;// 单词所在行
	boolean flag = true;//单词是否合法

	public Word() {

	}

	public Word(int id, String value, String type, int line) {
		this.id = id;
		this.value = value;
		this.type = type;
		this.line = line;
	}

	public static boolean isKey(String word) {
		return key.contains(word);
	}

	public static boolean isOperator(String word) {
		return operator.contains(word);
	}

	public static boolean isBoundarySign(String word) {
		return boundarySign.contains(word);
	}

	public static boolean isArOP(String word) {// 判断单词是否为算术运算符
		if ((word.equals("+") || word.equals("-") || word.equals("*") || word
				.equals("/")))
			return true;
		else
			return false;
	}

	public static boolean isBoolOP(String word) {// 判断单词是否为布尔运算符
		if ((word.equals(">") || word.equals("<") || word.equals("==")
				|| word.equals("!=") || word.equals("!") || word.equals("&&") || word
				.equals("||")))
			return true;
		else
			return false;
	}
}

Error.java

package compiler;

public class Error {
int id ;//错误序号;
String info;//错误信息;
int line ;//错误所在行
Word word;//错误的单词
public Error(){
	
}

public Error(int id,String info,int line,Word word){
	this.id=id;
	this.info=info;
	this.line=line;
	this.word=word;
}
}

LexAnalyse.java

package compiler;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;

/**
 * 词法分析器
 * 
 * 
 */
public class LexAnalyse {

	ArrayList<Word> wordList = new ArrayList<Word>();//单词表
	ArrayList<Error> errorList = new ArrayList<Error>();//错误信息列表
	int wordCount = 0;// 统计单词个数
	int errorCount = 0;// 统计错误个数
	boolean noteFlag = false;// 多行注释标志
	boolean lexErrorFlag = false;// 词法分析出错标志
	public LexAnalyse() {

	}

	public LexAnalyse(String str) {
		lexAnalyse(str);
	}
	
	/*以下方法是
	1)为了确定初始位 便于继续while
	2)判断while得到的word属于Word类中的哪一种type
	*/
	/**
	 * 单个字符 判断是否为数字
	 * 
	 * @param 
	 * @return
	 */
	private static boolean isDigit(char ch) {
		boolean flag = false;
		if ('0' <= ch && ch <= '9')
			flag = true;
		return flag;
	}

	/**
	 * 字符串 判断是否为数字int
	 * 
	 * @param string
	 * @return
	 */
	private static boolean isInteger(String word) {
		int i;
		boolean flag = false;
		for (i = 0; i < word.length(); i++) {
			if (Character.isDigit(word.charAt(i))) {
				continue;
			} else {
				break;
			}
		}
		if (i == word.length()) {
			flag = true;
		}
		return flag;
	}

	/**
 	 * 字符串 判断是否都是\char\
	 * @param 
	 * @return
	 */
	private static boolean isChar(String word) {
		boolean flag = false;
		int i = 0;
		char temp = word.charAt(i);
		if (temp == '\'') {
			for (i = 1; i < word.length(); i++) {
				temp = word.charAt(i);
				if (0 <= temp && temp <= 255)
					continue;
				else
					break;
			}
			if (i + 1 == word.length() && word.charAt(i) == '\'')
				flag = true;
		} else
			return flag;

		return flag;
	}

	/**
	 * 字符 判断是否为字母
	 * 
	 * @param ch
	 * @return
	 */
	private static boolean isLetter(char ch) {
		boolean flag = false;
		if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
			flag = true;
		return flag;
	}

	/**
	 * 字符串 判断是否为合法标识符ID
	 * 
	 * @param 
	 * @return
	 */
	private static boolean isID(String word) {
		boolean flag = false;
		int i = 0;
		if (Word.isKey(word))
			return flag;
		char temp = word.charAt(i);
		if (isLetter(temp) || temp == '_') {//字母或是_开头
			for (i = 1; i < word.length(); i++) {
				temp = word.charAt(i);
				if (isLetter(temp) || temp == '_' || isDigit(temp))//只含有字母、_、数字
					continue;
				else
					break;
			}
			if (i >= word.length())
				flag = true;
		} else
			return flag;

		return flag;
	}

	/**
	 * 判断词法分析是否出错了
	 * 
	 */
	public boolean isFail() {
		return lexErrorFlag;
	}

	public void analyse(String str, int line) {//str都是处理掉空白符号的 按行处理
		int beginIndex;
		int endIndex;
		int index = 0;
		int length = str.length();
		Word word = null;
		Error error;
		// boolean flag=false;
		char temp;
		while (index < length) {//
			temp = str.charAt(index);
			if (!noteFlag) {//不是多行注释
				if (isLetter(temp) || temp == '_') {//如果是字母或者_开头,就判断是不是标志符
					beginIndex = index; //初始为 0
					index++;
					// temp=str.charAt(index);
					while ((index < length)//while循环 直到出现&&中的各种情况
							&& (!Word.isBoundarySign(str.substring(index,index + 1)))//看开头除外的后面的 从beginIndex开始取,到endIndex结束,从0开始数,其中不包括endIndex位置的字符
							&& (!Word.isOperator(str.substring(index, index + 1)))
							&& (str.charAt(index) != ' ')
							&& (str.charAt(index) != '\t')
							&& (str.charAt(index) != '\r')
							&& (str.charAt(index) != '\n'))
					{
						index++;
					}
					endIndex = index;
					word = new Word();
					wordCount++;
					word.id = wordCount;
					word.line = line;//按行处理
					word.value = str.substring(beginIndex, endIndex);//把刚刚while得到的词存入wordList
					if (Word.isKey(word.value)) {
						word.type = Word.KEY;
					} else if (isID(word.value)) {
						word.type = Word.IDENTIFIER;
					} else {//如果上述都不是,那就是一个非法标识符
						word.type = Word.UNIDEF;
						word.flag = false;
						errorCount++;
						error = new Error(errorCount, "非法标识符", word.line, word);
						errorList.add(error);
						lexErrorFlag = true;
					}
					index--;//

				} else if (isDigit(temp)) {//如果初始位是数字 判断是不是int常数
					beginIndex = index;
					index++;
					while ((index < length)
							&& (!Word.isBoundarySign(str.substring(index,index + 1)))
							&& (!Word.isOperator(str.substring(index, index + 1)))
							&& (str.charAt(index) != ' ')
							&& (str.charAt(index) != '\t')
							&& (str.charAt(index) != '\r')
							&& (str.charAt(index) != '\n')) 
					{
						index++;
					}
					endIndex = index;
					word = new Word();
					wordCount++;//lexAnalyse中的全局变量
					word.id = wordCount;
					word.line = line;
					word.value = str.substring(beginIndex, endIndex);
					if (isInteger(word.value)) {
						word.type = Word.INT_CONST;
					} else {
						word.type = Word.UNIDEF;
						word.flag = false;//应该是用来标识不是错误符
						errorCount++;
						error = new Error(errorCount, "非法标识符", word.line, word);
						errorList.add(error);
						lexErrorFlag = true;
					}
					index--;
					
				} else if (String.valueOf(str.charAt(index)).equals("'")) {//当第一个是字符是'时 字符常量
					//flag=true;
					beginIndex = index;
					index++;
					temp = str.charAt(index);
					while (index < length && (0 <= temp && temp <= 255)) {
						if (String.valueOf(str.charAt(index)).equals("'"))//直到读到'
							break;
						index++;
						// temp=str.charAt(index);
					}
					if (index < length) {
						endIndex = index;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(beginIndex, endIndex);
						word.type = Word.CHAR_CONST;
						// flag=true;
						// word.flag=flag;
						index--;
					} else {
						endIndex = index;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(beginIndex, endIndex);
						word.type = Word.UNIDEF;
						word.flag = false;
						errorCount++;
						error = new Error(errorCount, "非法标识符", word.line, word);
						errorList.add(error);
						lexErrorFlag = true;
						index--;
					}
				} else if (temp == '=') {//当第一个字符是 = 时 就往后再来一个 看是 = 还是 ==
					beginIndex = index;
					index++;
					if (index < length && str.charAt(index) == '=') {
						endIndex = index + 1;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(beginIndex, endIndex);
						word.type = Word.OPERATOR;
					} else {
						// endIndex=index;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(index - 1, index);
						word.type = Word.OPERATOR;
						index--;
					}
				} else if (temp == '!') {//当第一个字符是 ! 就往后再来一个看是 ! 还是 !=
					beginIndex = index;
					index++;
					if (index < length && str.charAt(index) == '=') {
						endIndex = index + 1;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(beginIndex, endIndex);
						word.type = Word.OPERATOR;
						index++;
					} else {
						// endIndex=index;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(index - 1, index);
						word.type = Word.OPERATOR;
						index--;
					}
				} else if (temp == '&') {//当第一个字符是 & 就往后再来一个看是 & 还是 &&
					beginIndex = index;
					index++;
					if (index < length && str.charAt(index) == '&') {
						endIndex = index + 1;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(beginIndex, endIndex);
						word.type = Word.OPERATOR;
					} else {
						// endIndex=index;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(index - 1, index);
						word.type = Word.OPERATOR;
						index--;
					}
				} else if (temp == '|') {//当第一个字符是 | 就往后再来一个看是 | 还是 ||
					beginIndex = index;
					index++;
					if (index < length && str.charAt(index) == '|') {
						endIndex = index + 1;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(beginIndex, endIndex);
						word.type = Word.OPERATOR;
					} else {
						// endIndex=index;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(index - 1, index);
						word.type = Word.OPERATOR;
						index--;
					}
				} else if (temp == '+') {//当第一个字符是 + 就往后再来一个看是 + 还是 ++
					beginIndex = index;
					index++;
					if (index < length && str.charAt(index) == '+') {
						endIndex = index + 1;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(beginIndex, endIndex);
						word.type = Word.OPERATOR;

					} else {
						// endIndex=index;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(index - 1, index);
						word.type = Word.OPERATOR;
						index--;
					}
				} else if (temp == '-') {//当第一个字符是 - 就往后再来一个看是 - 还是 --
					beginIndex = index;
					index++;
					if (index < length && str.charAt(index) == '-') {
						endIndex = index + 1;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(beginIndex, endIndex);
						word.type = Word.OPERATOR;
					} else {
						// endIndex=index;
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(index - 1, index);
						word.type = Word.OPERATOR;
						index--;
					}
				} else if (temp == '/') {//当第一个字符是 / 就往后再来一个看是 / 还是 /* 还是//
					index++;
					if (index < length && str.charAt(index) == '/')
						break;//单行注释就不加了 直接跳出这一行 因为 单行注释只能在这一行的最后出现 反正也不需要编译
					/*
					 * { index++; while(str.charAt(index)!='\n'){ index++; } }
					 */
					else if (index < length && str.charAt(index) == '*') {//如果是多行注释
						noteFlag = true;
					} else {//只是单纯的除法
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = str.substring(index - 1, index);
						word.type = Word.OPERATOR;
					}
					index--;
				} else {// 不是标识符、数字常量、字符串常量

					switch (temp) {
					case ' ':
					case '\t':
					case '\r':
					case '\n':
						word = null;
						break;// 过滤空白字符
					case '[':
					case ']':
					case '(':
					case ')':
					case '{':
					case '}':
					case ',':
					case '"':
					case '.':
					case ';':
						// case '+':
						// case '-':
					case '*':
						// case '/':
					case '%':
					case '>':
					case '<':
					case '?':
					case '#':
						word = new Word();
						word.id = ++wordCount;
						word.line = line;
						word.value = String.valueOf(temp);
						if (Word.isOperator(word.value))
							word.type = Word.OPERATOR;
						else if (Word.isBoundarySign(word.value))
							word.type = Word.BOUNDARYSIGN;
						else
							word.type = Word.END;
						break;
					default://没考虑到的非法标识符
						word = new Word();
						wordCount++;
						word.id = wordCount;
						word.line = line;
						word.value = String.valueOf(temp);
						word.type = Word.UNIDEF;
						word.flag = false;
						errorCount++;
						error = new Error(errorCount, "非法标识符", word.line, word);
						errorList.add(error);
						lexErrorFlag = true;
					}
				}
			} else {//如果前面发现了/* 也就是多行注释 那么通过indexOf找到多行注释的结尾 把注释跳过
				int i = str.indexOf("*/");
				if (i != -1) {
					noteFlag = false;
					index = i + 2;
					continue;
				} else
					break;
			}
			if (word == null) {
				index++;
				continue;
			}
			wordList.add(word);
			index++;
		}
	}

	public ArrayList<Word> lexAnalyse(String str) {
		String buffer[];
		buffer = str.split("\n");
		int line = 1;
		for (int i = 0; i < buffer.length; i++) {
			analyse(buffer[i].trim(), line);
			line++;
		}
		if (!wordList.get(wordList.size() - 1).type.equals(Word.END)) {
			Word word = new Word(++wordCount, "#", Word.END, line++);
			wordList.add(word);
		}
		return wordList;
	}

	public ArrayList<Word> lexAnalyse1(String filePath) throws IOException {
		FileInputStream fis = new FileInputStream(filePath);
		BufferedInputStream bis = new BufferedInputStream(fis);
		InputStreamReader isr = new InputStreamReader(bis, "utf-8");
		BufferedReader inbr = new BufferedReader(isr);
		String str = "";
		int line = 1;
		while ((str = inbr.readLine()) != null) {
			// System.out.println(str);
			analyse(str.trim(), line);
			line++;
		}
		inbr.close();
		if (!wordList.get(wordList.size() - 1).type.equals(Word.END)) {
			Word word = new Word(++wordCount, "#", Word.END, line++);
			wordList.add(word);
		}
		return wordList;
	}

	public String outputWordList() throws IOException {//处理之后,返回一个文件名 供InfoFrame使用
		File file = new File("./output/");
		if (!file.exists()) {
			file.mkdirs();
			file.createNewFile();// 如果这个文件不存在就创建它
		}
		String path = file.getAbsolutePath();
		FileOutputStream fos = new FileOutputStream(path + "/wordList.txt");
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		OutputStreamWriter osw1 = new OutputStreamWriter(bos, "utf-8");
		PrintWriter pw1 = new PrintWriter(osw1);
		pw1.println("单词序号\t单词的值\t单词类型\t单词所在行\t单词是否合法");//mainframe显示的只是compiler里面的,难道mainframe与backup无关?
		Word word;
		for (int i = 0; i < wordList.size(); i++) {//数据取自wordList
			word = wordList.get(i);
			if(isInteger(word.value)) {//调整一下位置 使之对齐
				pw1.println(word.id + "\t\t" + word.value + "\t\t" + word.type + "\t" + word.line + "\t\t" + word.flag);
			}
			else {
			pw1.println(word.id + "\t\t" + word.value + "\t\t" + word.type + "\t" + "\t" + word.line + "\t\t" + word.flag);
			}
		}
		if (lexErrorFlag) {
			Error error;
			pw1.println("错误信息如下:");

			pw1.println("错误序号\t错误信息\t错误所在行 \t错误单词");
			for (int i = 0; i < errorList.size(); i++) {
				error = errorList.get(i);
				pw1.println(error.id + "\t" + error.info + "\t\t" + error.line
						+ "\t" + error.word.value);
			}
		} else {
			pw1.println("词法分析通过:");
		}
		pw1.close();
		return path + "/wordList.txt";
	}

	

	public static void main(String[] args) throws IOException {
		LexAnalyse lex = new LexAnalyse();
		lex.lexAnalyse1("b.c");
		lex.outputWordList();
	}
}

AnalyseNode.java

package compiler;

import java.util.ArrayList;

/**
 * 分析栈节点类
 *	String type;//节点类型
	String name;//节点名
	Object value;//节点值
 */
public class AnalyseNode {
	public final static String NONTERMINAL="非终结符";
	public final static String TERMINAL="终结符";
	public final static String ACTIONSIGN="动作符";
	public final static String END="结束符";
	static ArrayList<String>nonterminal=new ArrayList<String>();//非终结符集合
	static ArrayList<String>actionSign=new ArrayList<String>();//动作符集合
	static{
		//N:S,B,A,C,,X,R,Z,Z’,U,U’,E,E’,H,H’,G,M,D,L,L’,T,T’,F,O,P,Q
		nonterminal.add("S");
		nonterminal.add("A");
		nonterminal.add("B");
		nonterminal.add("C");
		nonterminal.add("D");
		nonterminal.add("E");
		nonterminal.add("F");
		nonterminal.add("G");
		nonterminal.add("H");
		nonterminal.add("L");
		nonterminal.add("M");
		nonterminal.add("O");
		nonterminal.add("P");
		nonterminal.add("Q");
		nonterminal.add("X");
		nonterminal.add("Y");
		nonterminal.add("Z");
		nonterminal.add("R");
		nonterminal.add("U");
		nonterminal.add("Z'");
		nonterminal.add("U'");
		nonterminal.add("E'");
		nonterminal.add("H'");
		nonterminal.add("L'");
		nonterminal.add("T");
		nonterminal.add("T'");
		actionSign.add("@ADD_SUB");
		actionSign.add("@ADD");
		actionSign.add("@SUB");
		actionSign.add("@DIV_MUL");
		actionSign.add("@DIV");
		actionSign.add("@MUL");
		actionSign.add("@SINGLE");
		actionSign.add("@SINGTLE_OP");
		actionSign.add("@ASS_R");
		actionSign.add("@ASS_Q");
		actionSign.add("@ASS_F");
		actionSign.add("@ASS_U");
		actionSign.add("@TRAN_LF");
		actionSign.add("@EQ");
		actionSign.add("@EQ_U'");
		actionSign.add("@COMPARE");
		actionSign.add("@COMPARE_OP");
		actionSign.add("@IF_FJ");
		actionSign.add("@IF_BACKPATCH_FJ");
		actionSign.add("@IF_RJ");
		actionSign.add("@IF_BACKPATCH_RJ");
		actionSign.add("@WHILE_FJ");
		actionSign.add("@WHILE_BACKPATCH_FJ");
		actionSign.add("@IF_RJ");
		actionSign.add("@FOR_FJ");
		actionSign.add("@FOR_RJ");
		actionSign.add("@FOR_BACKPATCH_FJ");
	}
	
	String type;//节点类型
	String name;//节点名
	String value;//节点值
	
	public static boolean isNonterm(AnalyseNode node){
		return nonterminal.contains(node.name);
	}
	public static boolean isTerm(AnalyseNode node){
		return Word.isKey(node.name)||Word.isOperator(node.name)||Word.isBoundarySign(node.name)
		||node.name.equals("id")||node.name.equals("num")||node.name.equals("ch");
	}
	public static boolean isActionSign(AnalyseNode node){
		return actionSign.contains(node.name);
	}
	public AnalyseNode(){
		
	}
public AnalyseNode(String type,String name,String value){
		this.type=type;
		this.name=name;
		this.value=value;
	}

}

FourElement.java

package compiler;

public class FourElement {
int id;//四元式序号,为编程方便
String op;//操作符
String arg1;//第一个操作数
String arg2;//第二个操作数
Object result;//结果
public FourElement(){
	
}
public FourElement(int id,String op,String arg1,String arg2,String result){
	this.id=id;
	this.op=op;
	this.arg1=arg1;
	this.arg2=arg2;
	this.result=result;	
}
}

Parser.java

package compiler;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Stack;
/**
 * 语法分析器
 * @author xxz
 *
 */
public class Parser {

	/**
	 * @param args
	 */
	
	private LexAnalyse lexAnalyse ;//词法分析器
	ArrayList<Word>wordList=new ArrayList<Word>();//单词表
	Stack<AnalyseNode>analyseStack=new Stack<AnalyseNode>();//分析栈
	Stack<String>semanticStack=new Stack<String>();//语义栈
	ArrayList<FourElement>fourElemList=new ArrayList<FourElement>();//四元式列表
	ArrayList<Error>errorList=new ArrayList<Error>();//错误信息列表
	StringBuffer bf;//分析栈缓冲流
	int errorCount=0;//统计错误个数
	boolean graErrorFlag=false;//语法分析出错标志
	int tempCount=0;//用于生成临时变量
	int fourElemCount=0;//统计四元式个数
	AnalyseNode S,B,A,C,X,Y,R,Z,Z1,U,U1,E,E1,H,H1,G,M,D,L,L1,T,T1,F,O,P,Q;
	AnalyseNode ADD_SUB,DIV_MUL,ADD,SUB,DIV,MUL,ASS_F,ASS_R,ASS_Q,ASS_U,TRAN_LF;
	AnalyseNode SINGLE,SINGLE_OP,EQ,EQ_U1,COMPARE,COMPARE_OP,IF_FJ,IF_RJ,IF_BACKPATCH_FJ,IF_BACKPATCH_RJ;
	AnalyseNode WHILE_FJ,WHILE_RJ,WHILE_BACKPATCH_FJ,FOR_FJ,FOR_RJ,FOR_BACKPATCH_FJ;
	AnalyseNode top;//当前栈顶元素
	Word firstWord;//待分析单词
	String OP=null;
	String ARG1,ARG2,RES;
	Error error;
	//int if_fj,if_rj,while_fj,while_rj,for_fj,for_rj;
	Stack<Integer>if_fj,if_rj,while_fj,while_rj,for_fj,for_rj;//if while for 跳转地址栈
	Stack<String>for_op=new Stack<String>();
	
public Parser(){
		
	}
public Parser(LexAnalyse lexAnalyse){
		this.lexAnalyse=lexAnalyse;
		this.wordList=lexAnalyse.wordList;
		init();
	}
private String newTemp(){
	tempCount++;
	return "T"+tempCount;
}
public void init(){
	S=new AnalyseNode(AnalyseNode.NONTERMINAL, "S", null);
	A=new AnalyseNode(AnalyseNode.NONTERMINAL, "A", null);
	B=new AnalyseNode(AnalyseNode.NONTERMINAL, "B", null);
	C=new AnalyseNode(AnalyseNode.NONTERMINAL, "C", null);
	X=new AnalyseNode(AnalyseNode.NONTERMINAL, "X", null);
	Y=new AnalyseNode(AnalyseNode.NONTERMINAL, "Y", null);
	Z=new AnalyseNode(AnalyseNode.NONTERMINAL, "Z", null);
	Z1=new AnalyseNode(AnalyseNode.NONTERMINAL, "Z'", null);
	U=new AnalyseNode(AnalyseNode.NONTERMINAL, "U", null);
	U1=new AnalyseNode(AnalyseNode.NONTERMINAL, "U'", null);
	E=new AnalyseNode(AnalyseNode.NONTERMINAL, "E", null);
	E1=new AnalyseNode(AnalyseNode.NONTERMINAL, "E'", null);
	H=new AnalyseNode(AnalyseNode.NONTERMINAL, "H", null);
	H1=new AnalyseNode(AnalyseNode.NONTERMINAL, "H'", null);
	G=new AnalyseNode(AnalyseNode.NONTERMINAL, "G", null);
	F=new AnalyseNode(AnalyseNode.NONTERMINAL, "F", null);
	D=new AnalyseNode(AnalyseNode.NONTERMINAL, "D", null);
	L=new AnalyseNode(AnalyseNode.NONTERMINAL, "L", null);
	L1=new AnalyseNode(AnalyseNode.NONTERMINAL, "L'", null);
	T=new AnalyseNode(AnalyseNode.NONTERMINAL, "T", null);
	T1=new AnalyseNode(AnalyseNode.NONTERMINAL, "T'", null);
	O=new AnalyseNode(AnalyseNode.NONTERMINAL, "O", null);
	P=new AnalyseNode(AnalyseNode.NONTERMINAL, "P", null);
	Q=new AnalyseNode(AnalyseNode.NONTERMINAL, "Q", null);
	R=new AnalyseNode(AnalyseNode.NONTERMINAL, "R", null);
	ADD_SUB=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@ADD_SUB", null);
	ADD=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@ADD", null);
	SUB=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@SUB", null);
	DIV_MUL=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@DIV_MUL", null);
	DIV=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@DIV", null);
	MUL=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@MUL", null);
	ASS_F=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@ASS_F", null);
	ASS_R=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@ASS_R", null);
	ASS_Q=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@ASS_Q", null);
	ASS_U=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@ASS_U", null);
	TRAN_LF=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@TRAN_LF", null);
	SINGLE=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@SINGLE", null);
	SINGLE_OP=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@SINGLE_OP", null);
	EQ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@EQ", null);
	EQ_U1=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@EQ_U'", null);
	COMPARE=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@COMPARE", null);
	COMPARE_OP=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@COMPARE_OP", null);
	IF_FJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@IF_FJ", null);
IF_RJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@IF_RJ", null);
IF_BACKPATCH_FJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@IF_BACKPATCH_FJ", null);
IF_BACKPATCH_RJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@IF_BACKPATCH_RJ", null);
 WHILE_FJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@WHILE_FJ", null);
WHILE_RJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@WHILE_RJ", null);
WHILE_BACKPATCH_FJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@WHILE_BACKPATCH_FJ", null);
FOR_FJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@FOR_FJ", null);
FOR_RJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@FOR_RJ", null);
FOR_BACKPATCH_FJ=new AnalyseNode(AnalyseNode.ACTIONSIGN, "@FOR_BACKPATCH_FJ", null);
if_fj=new Stack<Integer>();
if_rj=new Stack<Integer>();
while_fj=new Stack<Integer>();
while_rj=new Stack<Integer>();
for_fj=new Stack<Integer>();
for_rj=new Stack<Integer>();
	
}
public void grammerAnalyse(){//LL1分析方法进行语法分析
	if(lexAnalyse.isFail())javax.swing.JOptionPane.showMessageDialog(null, "词法分析未通过,不能进行语法分析");
	bf=new StringBuffer();
	int gcount=0;
	error=null;
	analyseStack.add(0,S);
	analyseStack.add(1,new AnalyseNode(AnalyseNode.END, "#", null));
	semanticStack.add("#");
	while(!analyseStack.empty() && !wordList.isEmpty()){
		//System.out.println(fourElemCount);
		bf.append('\n');
		bf.append("步骤"+gcount+"\t");
		if(gcount++>10000){//一万步就算了
			graErrorFlag=true;
			break;
		}
		/*
		 * 此方法接受整数数据类型的强制参数索引。
		 * 它指定要从堆栈中获取的元素的位置或索引。
		 * Java.util.Stack.get()方法用于从堆栈中获取或检索特定索引处的元素。
		 */
		top=analyseStack.get(0);//当前分析栈栈底元素(不是栈顶吧
		firstWord=wordList.get(0);//待分析单词
		if(firstWord.value.equals("#") && top.name.equals("#")){//正常结束
			bf.append("\n");
			analyseStack.remove(0);
			wordList.remove(0);
		}
		else if(top.name.equals("#")){//如果top == # 而first != # 则出错
			analyseStack.remove(0);
			graErrorFlag=true;
			break;
			
		}
		//以AnalyseStack中的top结点为触媒
		//!firstWord.value.equals("#") && !top.name.equals("#")
		else if(AnalyseNode.isTerm(top)){//语法分析栈top为终结符时的处理
			 termOP(top.name);
		}else if(AnalyseNode.isNonterm(top)){//语法分析栈top为非终结符时的处理
			nonTermOP(top.name);
		}else if(top.type.equals(AnalyseNode.ACTIONSIGN)){//语法分析栈top是动作符号时的处理
			actionSignOP();//top.name
		}
		
		bf.append("当前语法分析栈:");
		for(int i=0;i<analyseStack.size();i++){
			bf.append(analyseStack.get(i).name);
			//System.out.println(analyseStack.get(i).name);
		}
		bf.append("\t").append("余留符号串:");
		for(int j=0;j<wordList.size();j++){
			bf.append(wordList.get(j).value);
		}
		bf.append("\t").append("语义栈:");
		for(int k=semanticStack.size()-1;k>=0;k--){
			bf.append(semanticStack.get(k));
		}
	}
}

private void termOP(String term){
	if(firstWord.type.equals(Word.INT_CONST)
			||firstWord.type.equals(Word.CHAR_CONST)
			||term.equals(firstWord.value)//相等也行
			||(term.equals("id")&&firstWord.type.equals(Word.IDENTIFIER)))
	{
		analyseStack.remove(0);
		wordList.remove(0);
	}
		else{
		errorCount++;
		analyseStack.remove(0);
		wordList.remove(0);
		error=new Error(errorCount,"语法错误",firstWord.line,firstWord);
		errorList.add(error);
		graErrorFlag=true;
	}	
	
}
private void nonTermOP(String nonTerm){
	if(nonTerm.equals("Z'"))nonTerm="1";
	if(nonTerm.equals("U'"))nonTerm="2";
	if(nonTerm.equals("E'"))nonTerm="3";
	if(nonTerm.equals("H'"))nonTerm="4";
	if(nonTerm.equals("L'"))nonTerm="5";
	if(nonTerm.equals("T'"))nonTerm="6";
	switch(nonTerm.charAt(0)){//栈顶为非终结符处理
	//N:S,B,A,C,,X,R,Z,Z’,U,U’,E,E’,H,H’,G,M,D,L,L’,T,T’,F,O,P,Q
	case 'S':
	if(firstWord.value.equals("void")){
		analyseStack.remove(0);
		analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "void", null));
		analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "main", null));
		analyseStack.add(2,new AnalyseNode(AnalyseNode.TERMINAL, "(", null));
		analyseStack.add(3,new AnalyseNode(AnalyseNode.TERMINAL, ")", null));
		analyseStack.add(4,new AnalyseNode(AnalyseNode.TERMINAL, "{", null));
		analyseStack.add(5,A);
		analyseStack.add(6,new AnalyseNode(AnalyseNode.TERMINAL, "}", null));
	}else{//第一步就出错了
		errorCount++;
		analyseStack.remove(0);
		wordList.remove(0);
		error=new Error(errorCount,"主函数没有返回值",firstWord.line,firstWord);
		errorList.add(error);	
		graErrorFlag=true;
	}
		break;
	case 'A':
		if(firstWord.value.equals("int")||firstWord.value.equals("char")//A->CA
				||firstWord.value.equals("bool")){
			analyseStack.remove(0);
			analyseStack.add(0,C);
			analyseStack.add(1,A);
		}else if(firstWord.value.equals("printf")){
			analyseStack.remove(0);
			analyseStack.add(0,C);
			analyseStack.add(1,A);
			
		}
		else if(firstWord.value.equals("scanf")){
			analyseStack.remove(0);
			analyseStack.add(0,C);
			analyseStack.add(1,A);
		}
		else if(firstWord.value.equals("if")){
			analyseStack.remove(0);
			analyseStack.add(0,C);
			analyseStack.add(1,A);
		}
		else if(firstWord.value.equals("while")){
			analyseStack.remove(0);
			analyseStack.add(0,C);
			analyseStack.add(1,A);
		}
		else if(firstWord.value.equals("for")){
			analyseStack.remove(0);
			analyseStack.add(0,C);
			analyseStack.add(1,A);
			}
		else if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,C);
			analyseStack.add(1,A);
		}else{//A->$
			analyseStack.remove(0);
		}
		break;
	
	case 'B':
 if(firstWord.value.equals("printf")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "printf", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "(", null));
			analyseStack.add(2,P);
			analyseStack.add(3,new AnalyseNode(AnalyseNode.TERMINAL, ")", null));
			analyseStack.add(4,A);
			analyseStack.add(5,new AnalyseNode(AnalyseNode.TERMINAL, ";", null));
			
		}
		else if(firstWord.value.equals("scanf")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "scanf", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "(", null));
			analyseStack.add(2,new AnalyseNode(AnalyseNode.TERMINAL, "id", null));
			analyseStack.add(3,new AnalyseNode(AnalyseNode.TERMINAL, ")", null));
			analyseStack.add(4,A);
			analyseStack.add(5,new AnalyseNode(AnalyseNode.TERMINAL, ";", null));
		}
		else if(firstWord.value.equals("if")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "if", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "(", null));
			analyseStack.add(2,G);
			analyseStack.add(3,new AnalyseNode(AnalyseNode.TERMINAL, ")", null));
			analyseStack.add(4,IF_FJ);
			analyseStack.add(5,new AnalyseNode(AnalyseNode.TERMINAL, "{", null));
			analyseStack.add(6,A);
			analyseStack.add(7,new AnalyseNode(AnalyseNode.TERMINAL, "}", null));
			analyseStack.add(8,IF_BACKPATCH_FJ);
			analyseStack.add(9,IF_RJ);
			analyseStack.add(10,new AnalyseNode(AnalyseNode.TERMINAL, "else", null));
			analyseStack.add(11,new AnalyseNode(AnalyseNode.TERMINAL, "{", null));
			analyseStack.add(12,A);
			analyseStack.add(13,new AnalyseNode(AnalyseNode.TERMINAL, "}", null));
			analyseStack.add(14,IF_BACKPATCH_RJ);
		}
		else if(firstWord.value.equals("while")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "while", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "(", null));
			analyseStack.add(2,G);
			analyseStack.add(3,new AnalyseNode(AnalyseNode.TERMINAL, ")", null));
			analyseStack.add(4,WHILE_FJ);
			analyseStack.add(5,new AnalyseNode(AnalyseNode.TERMINAL, "{", null));
			analyseStack.add(6,A);
			analyseStack.add(7,new AnalyseNode(AnalyseNode.TERMINAL, "}", null));
			analyseStack.add(8,WHILE_RJ);
			analyseStack.add(9,WHILE_BACKPATCH_FJ);
		}
		else if(firstWord.value.equals("for")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "for", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "(", null));
			analyseStack.add(2,Y);
			analyseStack.add(3,Z);
			analyseStack.add(4,new AnalyseNode(AnalyseNode.TERMINAL, ";", null));
			analyseStack.add(5,G);
			analyseStack.add(6,FOR_FJ);
			analyseStack.add(7,new AnalyseNode(AnalyseNode.TERMINAL, ";", null));
			analyseStack.add(8,Q);
			analyseStack.add(9,new AnalyseNode(AnalyseNode.TERMINAL, ")", null));
			analyseStack.add(10,new AnalyseNode(AnalyseNode.TERMINAL, "{", null));
			analyseStack.add(11,A);
			analyseStack.add(12,SINGLE);
			analyseStack.add(13,new AnalyseNode(AnalyseNode.TERMINAL, "}", null));
			analyseStack.add(14,FOR_RJ);
			analyseStack.add(15,FOR_BACKPATCH_FJ);
		}
		else{
			analyseStack.remove(0);
		}
		break;
	case 'C'://C->X|B|R
		
			analyseStack.remove(0);
			analyseStack.add(0,X);
			analyseStack.add(1,B);
			analyseStack.add(2,R);
		break;
	case 'X':
		if(firstWord.value.equals("int")||firstWord.value.equals("char")||firstWord.value.equals("bool")){
			analyseStack.remove(0);
			analyseStack.add(0,Y);
			analyseStack.add(1,Z);
			analyseStack.add(2,new AnalyseNode(AnalyseNode.TERMINAL, ";", null));
		}else{
			analyseStack.remove(0);
		}
		break;
	case 'Y':
		if(firstWord.value.equals("int")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "int", null));
		}
		else if(firstWord.value.equals("char")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "char", null));
		}
		else if(firstWord.value.equals("bool")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "bool", null));
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"非法数据类型",firstWord.line,firstWord);
			errorList.add(error);	
			graErrorFlag=true;
		}
		break;
	case 'Z':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,U);
			analyseStack.add(1,Z1);//Z1即为一个analyseNode(z’)
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"非法标识符",firstWord.line,firstWord);
			errorList.add(error);
			graErrorFlag=true;
		}
		break;
	case '1'://z'
		if(firstWord.value.equals(",")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, ",", null));
			analyseStack.add(1,Z);
		}
		else{
			analyseStack.remove(0);
		}
		break;
	case 'U':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,ASS_U);//actionSignOP
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "id", null));//助于下一步删除wordList中的顶值(已经拷贝到semanticStack中)
			analyseStack.add(2,U1);
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"非法标识符",firstWord.line,firstWord);
			errorList.add(error);
			graErrorFlag=true;
		}
		break;
	case '2'://U'
		if(firstWord.value.equals("=")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "=", null));
			analyseStack.add(1,L);
			analyseStack.add(2,EQ_U1);
		}
		else{//有 = 但是没赋值 就走这条路
			analyseStack.remove(0);
		}
		break;
	case 'R':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.ACTIONSIGN, "@ASS_R", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "id", null));
			analyseStack.add(2,new AnalyseNode(AnalyseNode.TERMINAL, "=", null));
			analyseStack.add(3,L);
			analyseStack.add(4,EQ);
			analyseStack.add(5,new AnalyseNode(AnalyseNode.TERMINAL, ";", null));
		}
		else{
			analyseStack.remove(0);
		}
		break;
	case 'P':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "id", null));
		}else if(firstWord.type.equals(Word.INT_CONST)){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "num", null));
		}else if(firstWord.type.equals(Word.CHAR_CONST)){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "ch", null));
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"不能输出的数据类型",firstWord.line,firstWord);
			errorList.add(error);	
			graErrorFlag=true;
		}
		break;
	case 'E':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,H);
			analyseStack.add(1,E1);
		}else if(firstWord.type.equals(Word.INT_CONST)){
			analyseStack.remove(0);
			analyseStack.add(0,H);
			analyseStack.add(1,E1);
		}else if(firstWord.value.equals("(")){
			analyseStack.remove(0);
			analyseStack.add(0,H);
			analyseStack.add(1,E1);
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"不能进行算术运算的数据类型",firstWord.line,firstWord);
			errorList.add(error);	
			graErrorFlag=true;
		}
		break;
	case '3'://E'
		if(firstWord.value.equals("&&")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "&&", null));
			analyseStack.add(1,E);
		}else {
			analyseStack.remove(0);
		}
		break;
	case 'H':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,G);
			analyseStack.add(1,H1);
		}else if(firstWord.type.equals(Word.INT_CONST)){
			analyseStack.remove(0);
			analyseStack.add(0,G);
			analyseStack.add(1,H1);
		}else if(firstWord.value.equals("(")){
			analyseStack.remove(0);
			analyseStack.add(0,G);
			analyseStack.add(1,H1);
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"不能进行算术运算的数据类型",firstWord.line,firstWord);
			errorList.add(error);	
			graErrorFlag=true;
		}
		break;
	case '4'://H'
		if(firstWord.value.equals("||")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "||", null));
			analyseStack.add(1,E);
		}else {
			analyseStack.remove(0);
		}
		break;
	case 'D':
		if(firstWord.value.equals("==")){
			analyseStack.remove(0);
			analyseStack.add(0,COMPARE_OP);
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "==", null));
		}else if(firstWord.value.equals("!=")){
			analyseStack.remove(0);
			analyseStack.add(0,COMPARE_OP);
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "!=", null));
			
		}else if(firstWord.value.equals(">")){
			analyseStack.remove(0);
			analyseStack.add(0,COMPARE_OP);
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, ">", null));
		}else if(firstWord.value.equals("<")){
			analyseStack.remove(0);
			analyseStack.add(0,COMPARE_OP);
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "<", null));
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"非法运算符",firstWord.line,firstWord);
			errorList.add(error);	
			graErrorFlag=true;
		}
		break;
	case 'G':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,F);
			analyseStack.add(1,D);
			analyseStack.add(2,F);
			analyseStack.add(3,COMPARE);
		}else if(firstWord.type.equals(Word.INT_CONST)){
			analyseStack.remove(0);
			analyseStack.add(0,F);
			analyseStack.add(1,D);
			analyseStack.add(2,F);
			analyseStack.add(3,COMPARE);
		}
		else if(firstWord.value.equals("(")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "(", null));
			analyseStack.add(1,E);
			analyseStack.add(2,new AnalyseNode(AnalyseNode.TERMINAL, ")", null));
		}
		else if(firstWord.value.equals("!")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "!", null));
			analyseStack.add(1,E);
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"不能进行算术运算的数据类型或括号不匹配",firstWord.line,firstWord);
			errorList.add(error);
			graErrorFlag=true;
		}
		break;
	case 'L':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,T);
			analyseStack.add(1,L1);
			analyseStack.add(2,ADD_SUB);
		}else if(firstWord.type.equals(Word.INT_CONST)){
			analyseStack.remove(0);
			analyseStack.add(0,T);
			analyseStack.add(1,L1);
			analyseStack.add(2,ADD_SUB);
		}
		else if(firstWord.value.equals("(")){
			analyseStack.remove(0);
			analyseStack.add(0,T);
			analyseStack.add(1,L1);
			analyseStack.add(2,ADD_SUB);
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"不能进行算术运算的数据类型或括号不匹配",firstWord.line,firstWord);
			errorList.add(error);
			graErrorFlag=true;
		}
		break;
	case '5'://l'
		if(firstWord.value.equals("+")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "+", null));
			analyseStack.add(1,L);
			analyseStack.add(2,ADD);
		}
		else if(firstWord.value.equals("-")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "-", null));
			analyseStack.add(1,L);
			analyseStack.add(2,SUB);
		}else {
			analyseStack.remove(0);
		}
		break;

	case 'T':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,F);
			analyseStack.add(1,T1);
			analyseStack.add(2,DIV_MUL);
		}else if(firstWord.type.equals(Word.INT_CONST)){
			analyseStack.remove(0);
			analyseStack.add(0,F);
			analyseStack.add(1,T1);
			analyseStack.add(2,DIV_MUL);
		}
		else if(firstWord.value.equals("(")){
			analyseStack.remove(0);
			analyseStack.add(0,F);
			analyseStack.add(1,T1);
			analyseStack.add(2,DIV_MUL);
		}
		else{
			errorCount++;
			analyseStack.remove(0);
			wordList.remove(0);
			error=new Error(errorCount,"不能进行算术运算的数据类型",firstWord.line,firstWord);
			errorList.add(error);	
			graErrorFlag=true;
		}
		break;
	case '6'://T'
		if(firstWord.value.equals("*")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "*", null));
			analyseStack.add(1,T);
			analyseStack.add(2,MUL);
		}
		else if(firstWord.value.equals("/")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "/", null));
			analyseStack.add(1,T);
			analyseStack.add(2,DIV);
		}else {
			analyseStack.remove(0);
		}
		break;
	case 'F':
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,ASS_F);
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "id", null));
		}else if(firstWord.type.equals(Word.INT_CONST)){
			analyseStack.remove(0);
			analyseStack.add(0,ASS_F);
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "num", null));
		}else if(firstWord.value.equals("(")){
			analyseStack.add(0,new AnalyseNode(AnalyseNode.TERMINAL, "(", null));
			analyseStack.add(1,L);
			analyseStack.add(2,new AnalyseNode(AnalyseNode.TERMINAL, ")", null));
			analyseStack.add(3,TRAN_LF);
		}
		else{
			//errorCount++;
			analyseStack.remove(0);
		//	wordList.remove(0);
			//error=new Error(errorCount,"不能进行算术运算的数据类型",firstWord.line,firstWord);
			//errorList.add(error);
			//graErrorFlag=true;
		}
		break;
	case 'O':
		if(firstWord.value.equals("++")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.ACTIONSIGN, "@SINGLE_OP", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "++", null));
		}else if(firstWord.value.equals("--")){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.ACTIONSIGN, "@SINGLE_OP", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "--", null));

		}else {
			analyseStack.remove(0);
		}
		break;
	case 'Q'://Q
		if(firstWord.type.equals(Word.IDENTIFIER)){
			analyseStack.remove(0);
			analyseStack.add(0,new AnalyseNode(AnalyseNode.ACTIONSIGN, "@ASS_Q", null));
			analyseStack.add(1,new AnalyseNode(AnalyseNode.TERMINAL, "id", null));
			analyseStack.add(2,new AnalyseNode(AnalyseNode.TERMINAL, "O", null));
		}else {
			analyseStack.remove(0);
		}
		break;
		
	}
}

private void actionSignOP(){
	if(top.name.equals("@ADD_SUB")){
		if(OP!=null&&(OP.equals("+")||OP.equals("-"))){
			ARG2=semanticStack.pop();
			ARG1=semanticStack.pop();
			RES=newTemp();
			//fourElemCount++;
			FourElement fourElem=new FourElement(++fourElemCount,OP,ARG1,ARG2,RES);
			fourElemList.add(fourElem);
			L.value=RES;
			semanticStack.push(L.value);
			OP=null;
		}
		analyseStack.remove(0);
		
	}else if(top.name.equals("@ADD")){
		OP="+";
		analyseStack.remove(0);
	}else if(top.name.equals("@SUB")){
		OP="-";
		analyseStack.remove(0);
	}else if(top.name.equals("@DIV_MUL")){//确保不是*= /=
		if(OP!=null&&(OP.equals("*")||OP.equals("/"))){
			ARG2=semanticStack.pop();
			ARG1=semanticStack.pop();
			RES=newTemp();
			//fourElemCount++;
			FourElement fourElem=new FourElement(++fourElemCount,OP,ARG1,ARG2,RES);
			fourElemList.add(fourElem);
			T.value=RES;
			semanticStack.push(T.value);
			OP=null;
		}
		analyseStack.remove(0);
	}
	else if(top.name.equals("@DIV")){
		OP="/";
		analyseStack.remove(0);
		}
	else if(top.name.equals("@MUL")){
		OP="*";
		analyseStack.remove(0);
	}else if(top.name.equals("@TRAN_LF")){
		F.value=L.value;
		//semanticStack.push(F.value);
		analyseStack.remove(0);
	}else if(top.name.equals("@ASS_F")){
		F.value=firstWord.value;
		semanticStack.push(F.value);
		analyseStack.remove(0);
	}else if(top.name.equals("@ASS_R")){
		R.value=firstWord.value;
		semanticStack.push(R.value);
		analyseStack.remove(0);
	}else if(top.name.equals("@ASS_Q")){
		Q.value=firstWord.value;
		semanticStack.push(Q.value);
		analyseStack.remove(0);
	}
	else if(top.name.equals("@ASS_U")){
		U.value=firstWord.value;
		semanticStack.push(U.value);
		analyseStack.remove(0);
	}else if(top.name.equals("@SINGLE")){
		if(for_op.peek()!=null){
			ARG1=semanticStack.pop();
			RES=ARG1;
			//fourElemCount++;
			FourElement fourElem=new FourElement(++fourElemCount,for_op.pop(),ARG1,"/",RES);
			fourElemList.add(fourElem);
		}
		analyseStack.remove(0);
	}else if(top.name.equals("@SINGLE_OP")){
		for_op.push(firstWord.value);
		analyseStack.remove(0);
	}else if(top.name.equals("@EQ")){
		OP="=";
		ARG1=semanticStack.pop();
		RES=semanticStack.pop();;
		//fourElemCount++;
		FourElement fourElem=new FourElement(++fourElemCount,OP,ARG1,"/",RES);
		fourElemList.add(fourElem);
		OP=null;
		analyseStack.remove(0);
	}
	else if(top.name.equals("@EQ_U'")){
		OP="=";
		ARG1=semanticStack.pop();
		RES=semanticStack.pop();;
		//fourElemCount++;
		FourElement fourElem=new FourElement(++fourElemCount,OP,ARG1,"/",RES);//  /代表 = 的另外一个操作数缺失 即为单目运算
		fourElemList.add(fourElem);
		OP=null;
		analyseStack.remove(0);
	}else if(top.name.equals("@COMPARE")){
		ARG2=semanticStack.pop();
		OP=semanticStack.pop();
		ARG1=semanticStack.pop();
		RES=newTemp();
		//fourElemCount++;
		FourElement fourElem=new FourElement(++fourElemCount,OP,ARG1,ARG2,RES);
		fourElemList.add(fourElem);
		G.value=RES;
		semanticStack.push(G.value);
		OP=null;
		analyseStack.remove(0);
	}else if(top.name.equals("@COMPARE_OP")){
		D.value=firstWord.value;
		semanticStack.push(D.value);
		analyseStack.remove(0);
	}else if(top.name.equals("@IF_FJ")){
		OP="FJ";
		ARG1=semanticStack.pop();
		FourElement fourElem=new FourElement(++fourElemCount,OP,ARG1,"/",RES);
		if_fj.push(fourElemCount);
		fourElemList.add(fourElem);
		OP=null;
		analyseStack.remove(0);
	}else if(top.name.equals("@IF_BACKPATCH_FJ")){
		backpatch(if_fj.pop(), fourElemCount+2);
		analyseStack.remove(0);
	}else if(top.name.equals("@IF_RJ")){
		OP="RJ";
		FourElement fourElem=new FourElement(++fourElemCount,OP,"/","/","/");
		if_rj.push(fourElemCount);
		fourElemList.add(fourElem);
		OP=null;
		analyseStack.remove(0);
	}else if(top.name.equals("@IF_BACKPATCH_RJ")){
		backpatch(if_rj.pop(), fourElemCount+1);
		analyseStack.remove(0);
	}else if(top.name.equals("@WHILE_FJ")){
		OP="FJ";
		ARG1=semanticStack.pop();
		FourElement fourElem=new FourElement(++fourElemCount,OP,ARG1,"/","/");
		while_fj.push(fourElemCount);
		fourElemList.add(fourElem);
		OP=null;
		analyseStack.remove(0);
	}else if(top.name.equals("@WHILE_RJ")){
		OP="RJ";
		RES=(while_fj.peek()-1)+"";
		FourElement fourElem=new FourElement(++fourElemCount,OP,"/","/",RES);
		for_rj.push(fourElemCount);
		fourElemList.add(fourElem);
		OP=null;
		analyseStack.remove(0);
	}else if(top.name.equals("@WHILE_BACKPATCH_FJ")){
		backpatch(while_fj.pop(), fourElemCount+1);
		analyseStack.remove(0);
	}else if(top.name.equals("@FOR_FJ")){
		OP="FJ";
		ARG1=semanticStack.pop();
		FourElement fourElem=new FourElement(++fourElemCount,OP,ARG1,"/","/");
		for_fj.push(fourElemCount);
		fourElemList.add(fourElem);
		OP=null;
		analyseStack.remove(0);//除去Ti
	}else if(top.name.equals("@FOR_RJ")){
		OP="RJ";
		RES=(for_fj.peek()-1)+"";
		FourElement fourElem=new FourElement(++fourElemCount,OP,"/","/",RES);
		for_rj.push(fourElemCount);
		fourElemList.add(fourElem);
		OP=null;
		analyseStack.remove(0);
	}else if(top.name.equals("@FOR_BACKPATCH_FJ")){
		backpatch(for_fj.pop(), fourElemCount+1);
		analyseStack.remove(0);
	}
	
	
}
private void backpatch(int i,int res){
FourElement temp=fourElemList.get(i-1);
temp.result=res+"";
fourElemList.set(i-1, temp);
}
public String outputLL1() throws IOException{
	//grammerAnalyse();
	File file=new File("./output/");
	if(!file.exists()){
		file.mkdirs();
		file.createNewFile();//如果这个文件不存在就创建它
	}
	String path=file.getAbsolutePath();
	FileOutputStream fos=new FileOutputStream(path+"/LL1.txt");  
	BufferedOutputStream bos=new BufferedOutputStream(fos); 
	OutputStreamWriter osw1=new OutputStreamWriter(bos,"utf-8");
	PrintWriter pw1=new PrintWriter(osw1);
	pw1.println(bf.toString());
	bf.delete(0, bf.length());
	if(graErrorFlag){
		Error error;
		pw1.println("错误信息如下:");
	
	pw1.println("错误序号\t错误信息\t错误所在行 \t错误单词");
	for(int i=0;i<errorList.size();i++){
		error=errorList.get(i);
		pw1.println(error.id+"\t"+error.info+"\t\t"+error.line+"\t"+error.word.value);
	}
	}else {
		pw1.println("语法分析通过:");
	}
	pw1.close();
	return path+"/LL1.txt";
}
public String outputFourElem() throws IOException{
	
	File file=new File("./output/");
	if(!file.exists()){
		file.mkdirs();
		file.createNewFile();//如果这个文件不存在就创建它
	}
	String path=file.getAbsolutePath();
	FileOutputStream fos=new FileOutputStream(path+"/FourElement.txt");  
	BufferedOutputStream bos=new BufferedOutputStream(fos); 
	OutputStreamWriter osw1=new OutputStreamWriter(bos,"utf-8");
	PrintWriter pw1=new PrintWriter(osw1);
	pw1.println("生成的四元式如下");
	pw1.println("序号(OP,ARG1,ARG2,RESULT)");
	FourElement temp;
	for(int i=0;i<fourElemList.size();i++){
		temp=fourElemList.get(i);
		pw1.println(temp.id+"("+temp.op+","+temp.arg1+","+temp.arg2+","+temp.result+")");
	}
	pw1.close();
	
	return path+"/FourElement.txt";
}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

huibian.java

package compiler;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import java.awt.*;

public class huibian extends JFrame {

	//private static final long serialVersionUID = 8766059377195109228L;
	private static String title;
	private static String fileName;
	private static TextArea text;
	
	private static boolean isInteger(String word) {
		int i;
		boolean flag = false;
		for (i = 0; i < word.length(); i++) {
			if (Character.isDigit(word.charAt(i))) {
				continue;
			} else {
				break;
			}
		}
		if (i == word.length()) {
			flag = true;
		}
		return flag;
	}
	
	public huibian() {
		init();
		
	}
public huibian(String title,String fileName){//huibian inf = new huibian("目标代码生成", fourElementPath);
	this.title=title;
	this.fileName=fileName;
	int count = 0;
	init();
	this.setTitle(title);
	try {
		String str[] =readFile(fileName).split("\n");
		String str_1 = "生成的目标代码如下\n";
		String str_2 = "序号(OP,ARG1,ARG2)\n";
		text.append(str_1);
		text.append(str_2);
		for(int i = 2; i < str.length; i++)
		{
			String temp[] = str[i].split(",");
			if(temp[0].charAt(temp[0].length() -1) == '='){//=
				
				//if(temp[1].substring(0,temp[1].length()-1).equals("T"))
				//{
				//String temp1 = temp[0].substring(0,temp[0].length() - 2) + "\n";
				//text.append(temp1);	
				//}
				//else {
				String temp1 = ++count + " MOV " + temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";
				//System.out.println(temp1);
				text.append(temp1);
				//}
			}
			//++
			else if(temp[0].charAt(temp[0].length() -1) == '+' && temp[0].charAt(temp[0].length() -2) == '+'){
				String temp1 = ++count + " INC "  + temp[1] + "\n";
				//System.out.println(temp1);
				text.append(temp1);
			}
			//+
			else if(temp[0].charAt(temp[0].length() -1) == '+'){
				
				//if(isInteger(temp[1])) {
					String temp2 = ++count + " MOV " + "AX" + "," + temp[2] + "\n";
					String temp3 = ++count + " MOV " +  temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";
					String temp1 = ++count + " ADD " + temp[3].substring(0,temp[3].length() - 1) + "," + "AX" + "\n";//temp[3].substring(0,temp[3].length() - 1)
					text.append(temp2);
					text.append(temp3);
					text.append(temp1);
				//}
				//else {
				//String temp1 = temp[0].substring(0,temp[0].length() - 2) + " ADD " + temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";//temp[3].substring(0,temp[3].length() - 1)
				//System.out.println(temp1);
				//text.append(temp1);
				//}
			}
			//-
			else if(temp[0].charAt(temp[0].length() -1) == '-'){
				//String temp1 = ++count + " SUB " + temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";
				String temp2 = ++count + " MOV " + "AX" + "," + temp[2] + "\n";
				String temp3 = ++count + " MOV " +  temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";
				String temp1 = ++count + " SUB " + temp[3].substring(0,temp[3].length() - 1) + "," + "AX" + "\n";//temp[3].substring(0,temp[3].length() - 1)
				text.append(temp2);
				text.append(temp3);
				text.append(temp1);
				//System.out.println(temp1);
				//text.append(temp1);
			}
			//*
			else if(temp[0].charAt(temp[0].length() -1) == '*'){
				//String temp1 = ++count + " MUL " + temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";
				String temp2 = ++count + " MOV " + "AX" + "," + temp[2] + "\n";
				String temp3 = ++count + " MOV " +  temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";
				String temp1 = ++count + " MUL " + temp[3].substring(0,temp[3].length() - 1) + "," + "AX" + "\n";//temp[3].substring(0,temp[3].length() - 1)
				text.append(temp2);
				text.append(temp3);
				text.append(temp1);
				//System.out.println(temp1);
				//text.append(temp1);
			}
			///
			else if(temp[0].charAt(temp[0].length() -1) == '/'){
				//String temp1 = ++count + " DIV "  + temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";
				String temp2 = ++count + " MOV " + "AX" + "," + temp[2] + "\n";
				String temp3 = ++count + " MOV " +  temp[3].substring(0,temp[3].length() - 1) + "," + temp[1] + "\n";
				String temp1 = ++count + " DIV " + temp[3].substring(0,temp[3].length() - 1) + "," + "AX" + "\n";//temp[3].substring(0,temp[3].length() - 1)
				text.append(temp2);
				text.append(temp3);
				text.append(temp1);
				//System.out.println(temp1);
				//text.append(temp1);
			}
			//RJ
			else if(temp[0].charAt(temp[0].length() -1) == 'J' && temp[0].charAt(temp[0].length() -2) == 'R'){
				String temp1 = ++count + " JMP " + temp[3].substring(0,temp[3].length() - 1)  + "\n";
				//System.out.println(temp1);
				text.append(temp1);
			}
			//FJ
			else if(temp[0].charAt(temp[0].length() -1) == 'J' && temp[0].charAt(temp[0].length() -2) == 'F'){
				//String temp1 = temp[0].substring(0,temp[0].length() - 3) + " JZ " + temp[3].substring(0,temp[3].length() - 1)  + "\n";
				//String temp1 = temp[0].substring(0,temp[0].length() - 3) + " JMP " + temp[3].substring(0,temp[3].length() - 1)  + "\n";
				String temp1 = ++count + " JL " + temp[3].substring(0,temp[3].length() - 1)  + "\n";
				//System.out.println(temp1);
				text.append(temp1);
			}
			//>
			else if(temp[0].charAt(temp[0].length() -1) == '>'){
				String temp1 = ++count + " CMP " + temp[1] + "," + temp[2]  + "\n";
				//String temp2 = temp[0].substring(0,temp[0].length() - 2) + " JG " + temp[3].substring(0,temp[3].length() - 1)  + "\n";
				//System.out.println(temp1);
				text.append(temp1);
				//text.append(temp2);
			}
			//<
			else if(temp[0].charAt(temp[0].length() -1) == '<'){
				String temp1 = ++count + " CMP " + temp[1]  + "," + temp[2]  + "\n";
				//String temp2 = temp[0].substring(0,temp[0].length() - 2) + " JL " + temp[3].substring(0,temp[3].length() - 1)  + "\n";
				//System.out.println(temp1);
				text.append(temp1);
				//text.append(temp2);
			}
		}
		
	} catch (IOException e) {
		
		e.printStackTrace();
	}	
}
	private void init() {
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension screen = toolkit.getScreenSize();
		setSize(500, 400);
		super.setLocation(screen.width / 2 - this.getWidth() / 2, screen.height
				/ 2 - this.getHeight() / 2);
		setContentPane(createContentPane());
	}

	private Container createContentPane() {
		JPanel pane = new JPanel(new BorderLayout());
		text = new TextArea();
		//msg.setBackground(Color.green);
		text.setForeground(Color.BLUE);
		pane.add(BorderLayout.CENTER, text);
		return pane;
	}
	private String readFile(String filename) 
	throws IOException{
		StringBuilder sbr = new StringBuilder();
		String str;
			FileInputStream fis = new FileInputStream(filename);
			BufferedInputStream bis = new BufferedInputStream(fis);
			InputStreamReader isr = new InputStreamReader(bis, "UTF-8");
			BufferedReader in=new BufferedReader(isr);
			while((str=in.readLine())!=null){
				sbr.append(str).append('\n');
			}
			in.close();
			//text.setText(sbr.toString());
		return sbr.toString();
	}
	public static String getTitl() {
		return title;
	}

	public static void setTitl(String title) {
		huibian.title = title;
	}

	public static String getFileName() {
		return fileName;
	}

	public static void setFileName(String fileName) {
		huibian.fileName = fileName;
	}

	public static TextArea getText() {
		return text;
	}

	public static void setText(TextArea jText) {
		huibian.text = jText;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		huibian inf=new huibian("测试","test.txt");
inf.setVisible(true);
	}

}

MainFrame.java

package gui;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.swing.*;
import compiler.*;

public class MainFrame extends JFrame {

	TextArea sourseFile;//用来显示源文件的文本框
	String soursePath;// 源文件路径
	String LL1Path;
	String wordListPath;
	String fourElementPath;
	LexAnalyse lexAnalyse;
	
	Parser parser;
	public MainFrame() {
		this.init();
	}

	public void init() {

		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension screen = toolkit.getScreenSize();
		setTitle("C语言小型编译器");
		setSize(750, 480);
		super.setResizable(false);
		super.setLocation(screen.width / 2 - this.getWidth() / 2, screen.height / 2 - this.getHeight() / 2);
		this.setContentPane(this.createContentPane());
	}

	private JPanel createContentPane() {
		JPanel p = new JPanel(new BorderLayout());
		p.add(BorderLayout.NORTH, createUpPane());
		p.add(BorderLayout.CENTER, createcCenterPane());
		p.add(BorderLayout.SOUTH, creatBottomPane());
		// p.setBorder(new EmptyBorder(8,8,8,8));
		return p;
	}

	private Component createUpPane() {
		JPanel p = new JPanel(new FlowLayout());
		final FilePanel fp = new FilePanel("选择待分析文件");
		JButton button = new JButton("确定");
		button.addActionListener(new ActionListener() {
		
			@Override
			public void actionPerformed(ActionEvent e) {
				String text;
				try {
					soursePath = fp.getFileName();
					text = readFile(soursePath);
					sourseFile.setText(text);

				} catch (IOException e1) {
					e1.printStackTrace();
				}            

			}
		});
		p.add(fp);
		//p.add(fp1);
		p.add(button);
		return p;
	}

	private Component createcCenterPane() {
		JPanel p = new JPanel(new BorderLayout());
		JLabel label = new JLabel("源文件如下:");
		sourseFile = new TextArea();
		sourseFile.setText("");
		p.add(BorderLayout.NORTH, label);
		p.add(BorderLayout.CENTER, sourseFile);
		return p;
	}

	private Component creatBottomPane() {
		JPanel p = new JPanel(new FlowLayout());
		JButton bt1 = new JButton("词法分析");
		JButton bt2 = new JButton("语法分析");
		JButton bt4 = new JButton("中间代码生成");
		JButton bt5 = new JButton("目标代码生成");
		bt1.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					lexAnalyse=new LexAnalyse(sourseFile.getText());
					wordListPath = lexAnalyse.outputWordList();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				InfoFrame inf = new InfoFrame("词法分析", wordListPath);

				inf.setVisible(true);
			}
		});
		bt2.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
			lexAnalyse=new LexAnalyse(sourseFile.getText());
			parser=new Parser(lexAnalyse);
				try {
					parser.grammerAnalyse();
					LL1Path= parser.outputLL1();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				InfoFrame inf = new InfoFrame("语法分析", LL1Path);
				inf.setVisible(true);
			}
		});
		
		bt4.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					lexAnalyse=new LexAnalyse(sourseFile.getText());
					parser=new Parser(lexAnalyse);
					parser.grammerAnalyse();
					fourElementPath=parser.outputFourElem();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				InfoFrame inf = new InfoFrame("中间代码生成", fourElementPath);
				inf.setVisible(true);
			}
		});
		bt5.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					lexAnalyse=new LexAnalyse(sourseFile.getText());
					parser=new Parser(lexAnalyse);
					parser.grammerAnalyse();
					fourElementPath=parser.outputFourElem();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				huibian inf = new huibian("目标代码生成", fourElementPath);
				inf.setVisible(true);
			}
		});
		
		p.add(bt1);
		p.add(bt2);
		//p.add(bt3);
		p.add(bt4);
		p.add(bt5);
		return p;
	}

	public static String readFile(String fileName) throws IOException {
		StringBuilder sbr = new StringBuilder();
		String str;
		FileInputStream fis = new FileInputStream(fileName);
		BufferedInputStream bis = new BufferedInputStream(fis);
		InputStreamReader isr = new InputStreamReader(bis, "UTF-8");
		BufferedReader in = new BufferedReader(isr);
		while ((str = in.readLine()) != null) {
			sbr.append(str).append('\n');
		}
		in.close();
		return sbr.toString();
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MainFrame mf = new MainFrame();
		//TinyCompiler tinyCompiler = new TinyCompiler();
		//mf.tinyCompiler = tinyCompiler;
		mf.setVisible(true);
	}
}

class FilePanel extends JPanel {
	FilePanel(String str) {
		JLabel label = new JLabel(str);
		JTextField fileText = new JTextField(35);
		JButton chooseButton = new JButton("浏览...");
		this.add(label);
		this.add(fileText);
		this.add(chooseButton);
		clickAction ca = new clickAction(this);
		chooseButton.addActionListener(ca);
	}

	public String getFileName() {
		JTextField jtf = (JTextField) this.getComponent(1);
		return jtf.getText();    
	}

	// 按钮响应函数
	private class clickAction implements ActionListener {
		private Component cmpt;

		clickAction(Component c) {
			cmpt = c;
		}

		public void actionPerformed(ActionEvent event) {
			JFileChooser chooser = new JFileChooser();
			chooser.setCurrentDirectory(new File("."));
			int ret = chooser.showOpenDialog(cmpt);
			if (ret == JFileChooser.APPROVE_OPTION) {
				JPanel jp = (JPanel) cmpt;
				JTextField jtf = (JTextField) jp.getComponent(1);//获取组件
				jtf.setText(chooser.getSelectedFile().getPath());
			}
		}
	}
}

InfoFrame.java

package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import java.awt.*;

public class InfoFrame extends JFrame {

	private static final long serialVersionUID = 8766059377195109228L;
	private static String title;
	private static String fileName;
	
	private static TextArea text;
	
	public InfoFrame() {
		init();
		
	}
public InfoFrame(String title,String fileName){
	this.title=title;
	this.fileName=fileName;
	init();
	this.setTitle(title);
	try {
		readFile(fileName);
	} catch (IOException e) {
		
		e.printStackTrace();
	}	
}
	private void init() {
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension screen = toolkit.getScreenSize();
		setSize(500, 400);
		super.setLocation(screen.width / 2 - this.getWidth() / 2, screen.height / 2 - this.getHeight() / 2);
		setContentPane(createContentPane());
	}

	private Container createContentPane() {
		JPanel pane = new JPanel(new BorderLayout());
		text = new TextArea();
		//msg.setBackground(Color.blue);
		text.setForeground(Color.BLUE);
		pane.add(BorderLayout.CENTER, text);
		return pane;
	}
	
	private String readFile(String filename) 
	throws IOException{
		StringBuilder sbr = new StringBuilder();
		String str;
			FileInputStream fis = new FileInputStream(filename);
			BufferedInputStream bis = new BufferedInputStream(fis);
			InputStreamReader isr = new InputStreamReader(bis, "UTF-8");
			BufferedReader in=new BufferedReader(isr);
			while((str=in.readLine())!=null){
				sbr.append(str).append('\n');
			}
			in.close();
			text.setText(sbr.toString());
		return sbr.toString();
	}
	public static String getTitl() {
		return title;
	}

	public static void setTitl(String title) {
		InfoFrame.title = title;
	}

	public static String getFileName() {
		return fileName;
	}

	public static void setFileName(String fileName) {
		InfoFrame.fileName = fileName;
	}

	public static TextArea getText() {
		return text;
	}

	public static void setText(TextArea jText) {
		InfoFrame.text = jText;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
InfoFrame inf=new InfoFrame("测试","test.txt");
inf.setVisible(true);
	}

}

♻️ 资源

在这里插入图片描述

大小: 2.32MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87415791