泰宁新闻网

用C语言实现一个C语言的编译器

泰宁新闻网 http://www.tainingxinwen.cn 2021-02-20 10:40 出处:网络
c语言编译器,用C语言实现一个C语言的编译器 代码已经上传至Github,欢迎star及contribution

c语言编译器,用C语言实现一个C语言的编译器

代码已经上传至Github,欢迎star及contribution

用C语言实现一个C语言的编译器

目标:基于C0+文法的编译器,生成语法树,四元式,符号表,最后生成X86汇编(386)

接下来介绍一下整个的设计和实现思路 (C0+ 文法是指 以C0为基础,另外增加了一些C0没有的文法 )和在实现过程中遇到的问题,以及怎样解决。

本工程实现了以C0+文法为输入语言的采用C语言设计的编译器,采用递归子程序的方法来设计分析,可以生成intel386汇编(16位),可在DOXBox0.74环境下和masm6.11汇编生成可执行程序。

在参加完试点班后,我看了老师发的一些资料。完成一个编译器的步骤为:词法分析——>语法语义分析——>中间代码(四元式)——>生成汇编,首先从语法分析开始写起。

语法分析

写词法分析的时候,回想到老师上课讲过的内容,词法分析使用自动机完成,自动机的设计会决定你后面写代码的复杂程度,所以可多看一些资料来进行设计,当然有一些博客的博主做的也很不错,都可以参考。下面是我自己参考资料和博客,然后按照自己的思路设计的一个自动机(图有些丑)

用C语言实现一个C语言的编译器

图有点乱,需要静下心来看看。之后可以用直接状态机的编码方式来进行编写,也可以用逐步判断分支的方式来编写,我用的是后者,设计了状态表来进行判断分支。

在编写的过程中,首先要解决怎么来读数据,阅读了《编译原理及实践》中的源码,它采用的是行缓冲技术,当时也不很理解为什么不能直接一个一个字符的读,后台看了许多资料,其中有一篇文章解释的很好,特地将其复制与此:

(从小文件里读字符何必要采用这种十来个byte的buffer缓冲技术呢,当我自己实现的时候我才意识到它的重要性。在出错处理的时候,需要用到它来记录定位出错的位置,此外,在阅读需要回溯的个别文法的时候比如定义变量和定义函数具有相同的前三个词型,这时当判断出了是哪一类的时候需要回溯处理(虽然改写了文法消除了回溯但是回溯会使得程序更加好写,且并不会增加太多效率负担),行缓冲技术在这里就派上用场了,他可以直接读取前几个字符,而不需要再对文件指针进行处理。词法分析第二个值得一提的就是对于常数的处理了。有些同学采用读取有符号常数的方法,比如“-123”会被当做一个词语读入。但是我觉得这样会导致在语法分析中的极大不便。比如在处理“—123”,“+-123”等这种语句的时候会非常麻烦。于是我将常熟前面的符号都提出来,分别当成两个单词读入,这在后面的语法分析的过程中证明了这是一个非常好的设计选择。)

当然在编写词法分析的时候大家会有疑问,用不用写头文件的词法分析,答案是不用,对于输入输出等汇编都有相应的库可以调用,当然如果你和我一样当时没有选修汇编这门课程,不用担心,我后面会在生成汇编的部分,讲述自学汇编的过程。

 

词法分析的过程其实可以看做一个切词过程,不用考虑整个句子的语法,把切出来的词(一个token)存储起来即可。这些token在后面的语法语义分析需要用到。

 

语法语义分析

语法分析上课老师讲过LL分析法,LR分析法等,每种文法都要有自己的条件,老师建议我门使用递归下降分析法来进行语法分析,因为这是一种适合手写语法编译器的方法,并且非常简单,递归下降法对语言所用的文法有一些限制,但递归下降是现阶段主流的语法分析方法,因为它可以由开发人员高度控制,在提供错误信息方面也很有优势。就连微软C#官方的编译器也是手写而成的递归下降语法分析器。使用递归下降法编写语法分析器无需任何类库,编写简单的分析器时甚至连前面学习的词法分析库都无需使用。

因为我选用的上下文无关文法,所以要进行超前查看进行预测,这时我们识别的token就用上了。所以本着能用即可的原则,递归下降非常实用。你只需把每个相应的模块写好,比如for,while等,然后分析到for时如果里面有while就把写好的while模块调入即可,非常简单。

当然我们还要生成语法树,这就需要设计一个好的数据结构,数据结构往往不好设计,一般在分析的过程中会发现自己少存储一些信息,这时候再加就会非常麻烦,特别是如果是在四元式,符号表才发现信息缺失,这会使得开发变得艰辛。我使用的是劳顿那本书里对于语法分析所设计的数据结构,对于后面生成语法树和四元式打下了基础。

语义分析我写的不是很多,主要是对于语法分析时出现的不符合文法要求的内容,后面时间比较少,所以也没有再进行细致的语义分析,只要有不符合文法就直接报错,程序崩溃。

 

 

四元式分析

写四元式的过程并不是很难,只要思路理清,可以看一下书上的例题,后面要根据自己写的四元式来转汇编,所以四元式不用非要教科书般的格式。对于跳转的label可以先不用考虑是否有多余,调用一个label,编号就++,for,if和while的跳转大部分相同,但是for和while要进行循环,所以label设置还是与if有些区别。While和for需要在开头设置一个label便于循环。对于寄存器的分配,我一开始也是比较随意,比如对于一个赋值语句,我先把右边的值给一个寄存器,然后将这个寄存器的值给等号的右边的数,一开始我这么做是担心复杂的四元运算,不能使用一个简单的赋值四元式就能解决,所以对于像a=b 和return a这样语句寄存器就没有必要使用了,所以我在汇编前的优化主要是解决这问题。

 

符号表的分析

符号表大概分为main函数,以及自定义函数,符号的作用范围就是就像java中的代码块作用范围。

一开始我是使用劳顿那本书的发法,使用哈希函数。但是后来发现在转汇编的时候对于变量以及函数变量的搜索非常不方便。就在写四元式的时候对于每一个代码块的开始加了**start语句,结束时加了**end语句

 

优化的分析

主要目的减少寄存器的使用和四元式的语句,对转汇编提供便利

分析过程-自身是赋值语句,下一个是赋值语句,下一个可能会消失;比如:a=b

如果下一个不是赋值语句,则可能自己消失;比如 return a

自身不是赋值语句,下一个是赋值语句,下一个可能会消失;比如a=b+3;

如果下一个不是赋值语句,则一定不消失。

汇编的分析

因为当时没有选汇编这门课,在转汇编的过程还是比较痛苦的,把汇编自己看了一遍,我自学的是intel386汇编,由于时间的问题,只完成了加减乘除,以及while,for,if循环,并且均能在dosbox成功汇编,并且进行反汇编单步调试可以看到寄存器的结果与预计结果一致。在找环境的过程也是非常艰辛,我下载了一个dosbox以及masm 结果masm版本太低无法编译386汇编,而从网上找的masm6.11可以支持386汇编,但是不能链接,而且没有debug文件不能进行反汇编,只能生成obj文件,所以我将obj文件放在版本较低的masm中进行了链接。这一过程用了很长的时间,也加深了我对obj和exe文件的理解,知道了为什么要生成obj文件,以及exe文件的理解。

 

C0文法如下:

<加法运算符> ::= +|-
<乘法运算符>  ::= *|/
<关系运算符>  ::=  <|<=|>|>=|!=|==
<字母>   ::= _|a|...|z|A|...|Z
<数字>   ::= 0|<非零数字>
<非零数字>  ::= 1|...|9
<字符>    ::=  '<加法运算符>'|'<乘法运算符>'|'<字母>'|'<数字>'
<字符串>   ::=  "{十进制编码为32,33,35-126的ASCII字符}"

<程序>    ::= [<常量说明>][<变量说明>]{<有返回值函数定义>|<无返回值函数定义>}<主函数>
<常量说明> ::=  const<常量定义>;{ const<常量定义>;}
<常量定义>   ::=   int<标识符>=<整数>{,<标识符>=<整数>}
                                    | float<标识符>=<实数>{,<标识符>=<实数>}
                                    | char<标识符>=<字符>{,<标识符>=<字符>}
<无符号整数>  ::= <非零数字>{<数字>}
<整数>        ::= [+|-]<无符号整数>|0
<小数部分>    ::= <数字>{<数字>}|<空>
<实数>        ::= [+|-]<整数>[.<小数部分>]
<标识符>    ::=  <字母>{<字母>|<数字>}
<声明头部>   ::=  int<标识符> |float <标识符>|char<标识符>
<变量说明>  ::= <变量定义>;{<变量定义>;}
<变量定义>  ::= <类型标识符>(<标识符>|<标识符>‘[’<无符号整数>‘]’){,(<标识符>|<标识符>‘[’<无符号整数>‘]’ )}
<可枚举常量>   ::=  <整数>|<字符>
<类型标识符>      ::=  int | float | char
<有返回值函数定义>  ::=  <声明头部>‘(’<参数>‘)’ ‘{’<复合语句>‘}’
<无返回值函数定义>  ::= void<标识符>‘(’<参数>‘)’‘{’<复合语句>‘}’
<复合语句>   ::=  [<常量说明>][<变量说明>]<语句列>
<参数>    ::= <参数表>
<参数表>    ::=  <类型标识符><标识符>{,<类型标识符><标识符>}| <空>
<主函数>    ::= void main‘(’‘)’‘{’<复合语句>‘}’
<表达式>    ::= [+|-]<项>{<加法运算符><项>}
<项>     ::= <因子>{<乘法运算符><因子>}
<因子>    ::= <标识符>|<标识符>‘[’<表达式>‘]’|‘(’<表达式>‘)’|<整数>|<实数>|<字符>|<有返回值函数调用语句>         
<语句>    ::= <条件语句>|<循环语句>| ‘{’<语句列>‘}’|<有返回值函数调用语句>; 
                           |<无返回值函数调用语句>;|<赋值语句>;|<读语句>;|<写语句>;|<空>;|<情况语句>|<返回语句>;
<赋值语句>   ::=  <标识符>=<表达式>|<标识符>‘[’<表达式>‘]’=<表达式>
<条件语句>  ::=  if ‘(’<条件>‘)’<语句>
<条件>    ::=  <表达式><关系运算符><表达式>|<表达式> //表达式为0条件为假,否则为真
<循环语句>   ::=  while ‘(’<条件>‘)’<语句>
<情况语句>  ::=  switch ‘(’<表达式>‘)’ ‘{’<情况表><缺省> ‘}’
<情况表>   ::=  <情况子语句>{<情况子语句>}
<情况子语句>  ::=  case<可枚举常量>:<语句>
<缺省>   ::=  default : <语句>|<空>
<有返回值函数调用语句> ::= <标识符>‘(’<值参数表>‘)’
<无返回值函数调用语句> ::= <标识符>‘(’<值参数表>‘)’
<值参数表>   ::= <表达式>{,<表达式>}|<空>
<语句列>   ::= {<语句>}
<读语句>    ::=  scanf ‘(’<标识符>{,<标识符>}‘)’
<写语句>    ::= printf ‘(’ <字符串>,<表达式> ‘)’| printf ‘(’<字符串> ‘)’| printf ‘(’<表达式>‘)’
<返回语句>   ::=  return[‘(’<表达式>‘)’]     

 

语法树设计:

以一个简单的加减乘除的例子来进行讲解

int main()
{
int a;
int b;
int c;
a=1;
b=2;
c=(a+b)*3/2;
return 0;
}

语法树:

用C语言实现一个C语言的编译器

 

只能这样打印,这是一颗逻辑上的树

在同一列上代表之间为兄弟关系,如果错位一个制表符则代表父子关系。

真实的树应该是这样,相同的颜色代表同一辈分。

用C语言实现一个C语言的编译器

 

四元式

根据语法树进行,比如对于while,while算一个代码块,可以它的儿子,以及儿子的兄弟就可以生成一系列的四元式。

 

指令

示例

语义

(+ ,t#7 ,t#8 ,t#9 ,)

t#9= t#7 +t#8

(/ ,t#3 ,t#4 ,t#11 ,)

t#11 =t#3 /t#4

(* ,t#5 ,t#6 ,t#10 ,)

t#10 =t#5*t#6

(-,t#3 ,t#4 ,t#11 ,)

t#11=t#3-t#4

赋值

(= ,1 ,t#0 ,_ ,)

t#0=1

大于

(> ,t#3 ,t#4 ,t#2 ,)

t#2=t#3 -t#4

跳转

(jump ,L1 ,_ ,_ ,)

jum

如果不等

(if_f ,t#2 ,L0 ,_ ,)

Jmp L0

跳转位置

(lab ,L0 ,_ ,_ ,)

Label: L0

for循环

(for_cmp ,t#2 ,L1 ,_ ,)

Label:L1

 

 

 

 

汇编的学习

mul src:

16位:AX×srcÞDX:AX

32位:EAX×srcÞEDX:EAX

DIV:

16位:DX:AX÷src,商ÞAX, 余数ÞDX

32位:EDX:EAX÷src,商ÞEAX,余数ÞEDX

Push  如果是32位 要sp要减4 pop指令同

src数据进栈 ((E)SP减2/4)

(reg32,mem32,imm,  386+).

用C语言实现一个C语言的编译器

用C语言实现一个C语言的编译器

small模式通常代码段、数据段均不超过64k,代码段中的跳转和call均为near模式,即使用段偏移就能定位;

1)  格式:MOV DEST,SRC  dest=src

把一个字节,字或双字从源操作数SRC传送至目的操作数DEST

2)  EAX通常用于计算,ECX通常用于循环变量计数。ESP和EBP有专门用途,ESP指示栈指针(用于指示栈顶位置),而EBP则是基址指针(用于指示子程序或函数调用的基址指针)。

3)  sub al, ah    al = al – ah

4)  调用规则

为了加强程序员之间的协作及简化程序开发进程,设定一个函数调用规则非常必要,函数调用规则规定函数调用及返回的规则,只要遵照这种规则写的程序均可以正确执行,从而程序员不必关心诸如参数如何传递等问题;另一方面,在汇编语言中可以调用符合这种规则的高级语言所写的函数,从而将汇编语言程序与高级语言程序有机结合在一起。

调用规则分为两个方面,及调用者规则和被调用者规则,如一个函数A调用一个函数B,则A被称为调用者(Caller),B被称为被调用者(Callee)。下图显示一个调用过程中的内存中的栈布局:

5)  被调用者应该遵循如下规则:

1.  将ebp入栈,并将esp中的值拷贝到ebp中,其汇编代码如下:

   push ebp ; 保存当前ebp

  mov ebp,esp ; EBP设为当前堆栈指针

  sub esp, xxx ; 预留xxx字节给函数临时变量.

上述代码的目的是保存调用子程序之前的基址指针,基址指针用于寻找栈上的参数和局部变量。当一个子程序开始执行时,基址指针保存栈指针指示子程序的执行。为了在子程序完成之后调用者能正确定位调用者的参数和局部变量,ebp的值需要返回。

2.  在栈上为局部变量分配空间。

3.  保存callee-saved寄存器的值,callee-saved寄存器包括ebx,edi和esi,将ebx,edi和esi压栈。

在上述三个步骤完成之后,子程序开始执行,当子程序返回时,必须完成如下工作:

1.  将返回的执行结果保存在eax中

2.  弹出栈中保存的callee-saved寄存器值,恢复callee-saved寄存器的值(ESI和EDI)

3.  收回局部变量的内存空间。实际处理时,通过改变EBP的值即可:mov esp, ebp。

4.  通过弹出栈中保存的ebp值恢复调用者的基址寄存器值。

5.  执行ret指令返回到调用者程序

网址:http://www.cnblogs.com/YukiJohnson/archive/2012/10/27/2741836.html

  ESP,EBP 汇编参数传递

查看定义ESP是栈顶指针,EBP是存取堆栈指针

网址:http://www.cnblogs.com/huangyong9527/archive/2012/08/14/2637987.html

ebp只是存取某时刻的esp,这个时刻就是进入一个函数内后,cpu会将esp的值赋给ebp

  Esi,edi

汇编编译执行:

环境 DOSBox0.74

基本命令:

 

masm 1.asm    -------编译汇编源文件

link 1.obj    -------链接

1.exe     ------运行程序

debug 1.exe    -----调试程序

u         ------查看寄存器状态

quit      -----退出

cls      -------清屏  

 

汇编器:链接:https://pan.baidu.com/s/10_V9qMMEnXKHDnKKCEjEFg 密码:fsoh

 

用C语言实现一个C语言的编译器

得到汇编代码

用C语言实现一个C语言的编译器

用masm6.11进行汇编

用C语言实现一个C语言的编译器

生成obj文件

在DOSBox里进行链接然后进行反汇编

用C语言实现一个C语言的编译器

成功链接 生成exe文件

用C语言实现一个C语言的编译器

反汇编

用C语言实现一个C语言的编译器

 

样例程序,及查看寄存器内容,反汇编单步调试过程

用C语言实现一个C语言的编译器

正确的运行结果应该是 C=25*2/3=16

进行单步调试查看寄存器的内容以判断正确性

 

 

 

用C语言实现一个C语言的编译器

a=12 b=13已经取出

用C语言实现一个C语言的编译器

加法和乘法已经正确,接下来是除法,继续单步调试

用C语言实现一个C语言的编译器

得到正确结果c=16

 

最后贴一下工程代码,可能不是最终版本有一些漏洞

//main.c
#include "global.h"
#include"parse.h"


int main()
{
    printf(">>> scan     =====================================\n");
    scan();
    //printf("\nscan success!!\n\n");
    //printf("syntax tree ----------\n");
    printf("\n\n>>> ast     =====================================\n");
   parse();
    //printf("\nparse success!!\n\n");
    //start_symbtab();
    printf("\n\n>>> tac     =====================================\n");
  tac();
    printf("\n\n>>>after optimize     =====================================\n");
    printf("\nafter optimize\n\n");
 start_optimize();
    printf("\n\n>>> asm     =====================================\n");
  start_asm();
    //get_table();
    return 0;
}

 

//scan.c
#include "scan.h"
#include "global.h"

char* tokenstring();                                ///转换成字符串
static void get_nextline(FILE *in);                 ///获取下一行的代码
static void get_token();                            ///获取token
static int state_change(int state,char ch);         ///状态转换
static char *returnstring(int m,int n);             ///将识别的出来的token进行复制保存到数组中
static tokentype letterchange(char a[]);            ///键字的识别转换,如果为关键字, 则存储为关键字,不是关键字就是ID
static int is_digit(char ch);                       ///数字的判断
static int is_letter(char ch);                      ///字符的判断
static int is_keywords(char a[]);                   ///关键字的判断
static void print_token();                          ///输出
/**关键字数组**/
static char keywords[50][20]={ "char", "continue","break",
                                "else","for", "float","if","while",
                                "int","main","double","case",
                                "return","void","continue", "struct",
                                "switch","default"};  ///竟然有那么蠢的bug
int tokenno=0;                      ///token的数量 语法分析还要用
tokenrecord token_table[1000];           /**用于存放识别的的token**/
char linebuf[1000];                                 /**每一行代码缓冲区**/
int lineno=0;                                       /**lineno用于记录代码的行数;**/
int currentchar;                                    /**。currentchar为代码缓冲区的计数器**/
int line_num_table[1000]={0};                       /**line_num_table记录每一行最后一个记号的位置**/
tokentype token;

/***********************************************************
 * 功能:	表驱动
 **********************************************************/
static int transform_table[16][13]={{0,0,0,0,0,0,0,0,0,0,0,0,0},    ///-1 为出口
                        {2,0,0,5,0,6,0,10,8,12,0,0,0},
                        {2,3,-1,0,0,0,0,0,0,0,0,0,0},
                        {4,0,0,0,0,0,0,0,0,0,0,0,0},
                        {4,0,-1,0,0,0,0,0,0,0,0,0,0},
                        {5,0,0,5,-1,0,0,0,0,0,0,0,0},
                        {0,0,0,0,0,0,-1,7,0,0,0,0,0},
                        {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
                        {0,0,0,0,0,0,-1,9,0,0,0,0,0},
                        {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
                        {0,0,0,0,0,0,-1,11,0,0,0,0,0},
                        {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
                        {0,0,0,0,0,0,0,0,0,13,-1,0,0},
                        {0,0,0,0,0,0,0,0,0,0,0,14,15},
                        {0,0,0,0,0,0,0,0,0,0,0,14,15},
                        {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}};

/***********************************************************
 * 功能:	词法分析的入口函数
 1:利用行缓冲技术进行读取每一行的字符
 **********************************************************/
void scan()
{
    FILE *text;
    text= fopen("test13.c", "r");/**读取测试文件**/
	if(text!=NULL)
	{

		while(!feof(text))                                  /**文件直到循环中读到文件尾feof(fp)有两个返回值:如果遇到文件结束,函数feof(fp)的值为1,否则为0。**/
		{
			currentchar=0;                                  /**每读完一行重新清零**/
			get_nextline(text);                               /**获取每一行,并放在linebuf中,以'/0'结束**/
			lineno++;
			if (strcmp(linebuf, " ") == 0) /**比较设否是空串**/
            {
                continue;
            }
			while(currentchar<strlen(linebuf))              /**注意currentchar。strlen是不包括'/0'的!但是有换行符‘\n’**/
			{
                    get_token();

			}
			line_num_table[lineno]=tokenno-1;
		}
	}
	fclose(text);
	print_token();
}



/***********************************************************
 * 功能:	行缓冲的具体实现
 **********************************************************/
static void get_nextline(FILE *text)
{
	if (!fgets(linebuf, 9999, text))/**当最后一行输入只是一个回车,会返回错误**/
	{
		strcpy(linebuf, " ");
	}
}


/***********************************************************
 * 功能:	识别具体的token
 通过自动机和表驱动
 **********************************************************/
static void get_token()
{
	char ch=linebuf[currentchar];;
	int ncurrentchar=currentchar;
	if(ch==' '||ch=='\n'||ch=='\t')
    {
        currentchar++;
        return;
    }
    /**以下是不需要进行状态表驱动,直接一步可以识别的token: / + - ! { } . [ ]**/
	switch (ch)
	{
	    case '!':
			{
				if(linebuf[currentchar+1]=='=')
				{
					token_table[tokenno].tokenval=NOTEQU;
					currentchar=currentchar+2;
				}
				break;
			}
		case '+':
			{
			    if(linebuf[currentchar+1]=='+')
				{
				    token_table[tokenno].tokenval=pPLUS;
                    currentchar=currentchar+2;
                    break;
				}
				else
                {
                    token_table[tokenno].tokenval=PLUS;
                    currentchar++;
                    break;
                }
			}
		case'-':
			{
			    if(linebuf[currentchar+1]=='-')
				{
				    token_table[tokenno].tokenval=mMINUS;
                    currentchar=currentchar+2;
                    break;
				}
				else
				{
                    token_table[tokenno].tokenval=MINUS;
                    currentchar++;
                    break;
				}
			}
		case '*':
			{
				token_table[tokenno].tokenval=TIMES;
				currentchar++;
				break;
			}
		case '%':
			{
				token_table[tokenno].tokenval=MODE;
				currentchar++;
				break;
			}
		case '{':
			{
				token_table[tokenno].tokenval=L_DA;
				currentchar++;
				break;
			}
		case '}':
			{
				token_table[tokenno].tokenval=R_DA;
				currentchar++;
				break;
			}
		case '[':
			{
				token_table[tokenno].tokenval=L_ZH;
				currentchar++;
				break;
			}
		case ']':
			{
				token_table[tokenno].tokenval=R_ZH;
				currentchar++;
				break;
			}
		case '(':
			{
				token_table[tokenno].tokenval=L_XI;
				currentchar++;
				break;
			}
		case ')':
			{
				token_table[tokenno].tokenval=R_XI;
				currentchar++;
				break;
			}
		case ';':
			{
				token_table[tokenno].tokenval=FENH;
				currentchar++;
				break;
			}
        case ':':
			{
				token_table[tokenno].tokenval=MAOH;
				currentchar++;
				break;
			}
		case ',':
			{
				token_table[tokenno].tokenval=DOUH;
				currentchar++;
				break;
			}
		case '.':
			{
				token_table[tokenno].tokenval=DIAN;
				currentchar++;
				break;
			}
        case '&':
			{
				token_table[tokenno].tokenval=ADE;
				currentchar++;
				break;
			}
        case '|':
			{
				token_table[tokenno].tokenval=HUO;
				currentchar++;
				break;
			}

	default:
	{
            int state=1,newstate;
            while(1)/**利用状态表驱动,识别token过程**/
            {
                int col=state_change(state,ch);
                if(col==999)
                {
                    printf("ERROR!!!!!");
                }
                newstate=transform_table[state][col];
                if(newstate==-1) break;
                currentchar++;
                ch=linebuf[currentchar];
                state=newstate;
            }
            switch(state)
            {
            case 2: /**整型数字**/
                {
                    token_table[tokenno].tokenval=NUM;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    token_table[tokenno].numval=atof(token_table[tokenno].stringval);/**atof()将字符串转换为数字**/
                    break;
                }

            case 4:/**浮点数**/
                {
                    token_table[tokenno].tokenval=NUM;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    token_table[tokenno].numval=atof(token_table[tokenno].stringval);
                    break;
                }
            case 5:  /**如果是保留字,则保存保留字,若不是,则保存变量**/
                {
                        strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                        if(is_keywords(token_table[tokenno].stringval))
                        {
                            token_table[tokenno].tokenval=letterchange(token_table[tokenno].stringval);
                        }

                        else
                            token_table[tokenno].tokenval=ID;
                        break;
                }
            case 6:  /**布尔型 <**/
                {
                    token_table[tokenno].tokenval=SMALLER;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    break;
                }
            case 7:/**布尔型 <=**/
                {
                    token_table[tokenno].tokenval=SMALLEREQU;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    break;
                }
             case 8:/**布尔型 >**/
                {
                    token_table[tokenno].tokenval=BIGGER;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    break;
                }
            case 9:/**布尔型 >=**/
                {
                    token_table[tokenno].tokenval=BIGGEREQU;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    break;
                }

            case 10:/**布尔型 =**/
                {
                    token_table[tokenno].tokenval=EQUAL;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    break;
                }
            case 11:/**布尔型 ==**/
                {
                    token_table[tokenno].tokenval=IFEQU;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    break;
                }
             case 12:/**布尔型 / **/
                {
                    token_table[tokenno].tokenval=DIVIDE;
                    strcpy(token_table[tokenno].stringval,returnstring(ncurrentchar,currentchar-1));
                    break;
                }
            case 15:/**注释**/
                {
                    token_table[tokenno].tokenval=COMMENT;
                    break;
                }
            default:
                {
                    printf("error");
                }
            }
	}
	}
	tokenno++;
}



/***********************************************************
 * 功能:关键字的识别转换,如果为关键字,
 则存储为关键字,不是关键字就是ID
 **********************************************************/
tokentype letterchange(char a[])
{
    if(strcmp(a,"int")==0) return INT;
    if(strcmp(a,"break")==0) return BREAK;
    if(strcmp(a,"case")==0) return CASE;
    if(strcmp(a,"char")==0) return CHAR;
    if(strcmp(a,"continue")==0) return CONTINUE;
    if(strcmp(a,"double")==0) return DOUBLE;
    if(strcmp(a,"float")==0)return FLOAT;
	if(strcmp(a,"char")==0)return CHAR;
	if(strcmp(a,"void")==0)return VOID;
	if(strcmp(a,"main")==0)return MAIN;
	if(strcmp(a,"if")==0)return IF;
	if(strcmp(a,"else")==0)return ELSE;
	if(strcmp(a,"while")==0)return WHILE;
	if(strcmp(a,"printf")==0)return PRINTF;
	if(strcmp(a,"scanf")==0)return SCANF;
	if(strcmp(a,"for")==0)return FOR;
	if(strcmp(a,"return")==0)return RETURN;
	if(strcmp(a,"struct")==0)return STRUCT;
	if(strcmp(a,"default")==0)return DEFAULT;
	if(strcmp(a,"switch")==0) return SWITCH;
	if(strcmp(a,"break")==0) return BREAK;
	printf("error!!!");
}


/***********************************************************
 * 功能:	判断是否是关键字
 **********************************************************/
static int is_keywords(char a[])
{
    int i=0;

    for(;i<50;i++)
        if(strcmp(a,keywords[i])==0)/**相等则是保留字**/
        {
             return 1;
        }

    return 0;
}


/***********************************************************
 * 功能:	状态变化的实现,通过状态转换表
 **********************************************************/
static int state_change(int state,char ch)
{

    if(state==1)
    {
        if (is_digit(ch)) return 0;
        if (is_letter(ch)) return 3;
        if (ch=='<') return 5;
        if(ch=='>') return 8;
        if(ch=='=') return 7;
        if(ch=='/') return 9;
    }
    if(state==2)
    {
        if(is_digit(ch)) return 0;
        if(ch=='.')  return 1;
        else return 2;
    }

    if(state==3)
    {
        if(is_digit(ch)) return 0;
    }

    if(state==4)
    {
        if(is_digit(ch)) return 0;
        else return 2;
    }

    if(state==5)
    {
        if(is_digit(ch)||is_letter(ch)) return 0;
        return 4;
    }

    if(state==6||state==8||state==10)
    {
        if(ch=='=') return 7;
        else return 6;
    }

     if(state==7||state==9||state==11||state==15)
    {
        return 0;
    }
    if(state==12)
    {
        if(ch=='/') return 9;
        if(ch!='=')return 10;
    }
     if(state==13||state==14)
    {

        if(ch=='\n'){ return 12;}
        else return 11;
    }
    return 999;

}


/***********************************************************
* 功能:	将识别的出来的token进行复制保存到数组中
**********************************************************/

static char * returnstring(int m,int n)
{
    int i=0;
    char s[200];
    for(;i<=(n-m);i++)
    {
        s[i]=linebuf[m+i];
    }
    s[i]='\0';
    return s;
}
/***********************************************************
* 功能:	1.判断是否为char
2.判断是否为数字
**********************************************************/

static int is_letter(char ch)
{
    if(('a'<=ch&&ch<='z')||('A'<=ch&&ch<='Z'))return 1;
	else return 0;
}

static int is_digit(char ch)
{
    if('0'<=ch&&ch<='9') return 1;
    else return 0;
}

/***********************************************************
* 功能: 输出的时候进行的字符转换
**********************************************************/
char* tokenstring()
{
	switch (token)
	{
	case INT :
	    return "int";
	case FLOAT:
	    return "float";
	case CHAR:
	    return "char";
	case DOUBLE:
	    return "double";
	case VOID:
	    return "void";
	case MAIN:
	    return "main";
	case IF:
	    return "if";
	case ELSE:
	    return "else";
	case WHILE:
	    return "while";
	case PRINTF:
	    return "printf";
	case SCANF:
	    return "scanf";
	case FOR:
	    return "for";
	case EQUAL:
	    return "=";
	case PLUS:
	    return "+";
	case pPLUS:
	    return "++";
	case MINUS:
	    return "-";
	case mMINUS:
	    return "--";
	case TIMES:
	    return "*";
	case DIVIDE:
	    return "/";
	case MODE:
	    return "%";
	case SMALLER:
	    return "<";
	case SMALLEREQU:
	    return "<=";
	case BIGGER:
	    return ">";
	case BIGGEREQU:
	    return ">=";
	case NOTEQU:
	    return "!=";
	case IFEQU:
	    return "==";
    case ADE:
	    return "&";
    case HUO:
	    return "|";
	case L_DA:
	    return "{";
	case R_DA:
	    return "}";
	case L_ZH:
	    return "[";
	case R_ZH:
	    return "]";
	case L_XI:
	    return "(";
	case R_XI:
	    return ")";
	case FENH:
	    return ";";
    case MAOH:
        return ":";
	case DOUH:
	    return ",";
	case DIAN:
	    return ".";
	case NUM:
	    return  "number";
	case ID:
	    return "id";
	case RETURN:
	    return "return";
	case COMMENT:
	    return "注释";
    case STRUCT:
        return "struct";
    case CASE:
        return "case";
    case DEFAULT:
        return "default";
    case SWITCH:
        return "switch";
    case BREAK:
        return "break";
    default:
        printf("error!!!无法匹配!!!");
	}
}


/***********************************************************
* 功能:用于输出token
**********************************************************/
static void print_token()
{

	int i;
	//printf("tokenno=%d\n",tokenno);
	int j;
	for(j=1;line_num_table[j]!=0;j++)
	{
	    printf("%d: ",j);
		for(i=line_num_table[j-1];i<=line_num_table[j];i++)
		{
		    if(j!=1&&i==line_num_table[j-1])
            {
                i++;
            }
			token=token_table[i].tokenval;
			printf("[%s] ",tokenstring());
		}
		printf("\n");
	}

}
//parse.c
#include "parse.h"
#include "global.h"
static treenode * entitypara_list();  ///用于自定义函数的参数
static treenode * BUER_stmt();        ///布尔运算语句
static treenode * newlnodestmt(Stmtkind stmt); ///申请语句结构结点
static treenode * newlnodeexp(Expkind exp);    ///申请算式结构结点
static treenode * term();                      ///带乘除的算术式
static treenode * factor();                    ///主要对于加减已经更低等级模块
static treenode * structure_stmt();             ///一个代码块{}
static treenode * instmt_sequence();            ///语句结构集合
static treenode * for_stmt();                   ///for语句
static treenode * while_stmt();                 ///while语句
static treenode * if_stmt();                    ///if语句
static treenode * switch_stmt();                ///switch语句
static treenode * case_stmt();                  ///case语句
static treenode * break_stmt();                 ///break语句
static treenode * default_stmt();               ///default语句
static treenode * statement();                  ///基本语句
static treenode * definepara_stmt();            ///定义参数
static treenode * quotepara_list();             ///函数调用的参数
static treenode * exp2();                       ///四则运算
static treenode * fun_apply();                  ///函数调用
static treenode * assign_stmt();                ///赋值语句
static treenode * define_assign();              ///定义语句
static treenode * exp();                        ///四则运算的更低模块
static treenode * simple_exp();                 ///更简单的运算模块
static treenode * input_para_list();            ///输入的参数
static treenode * struct_stmt();                ///结构体语句
int isin_first_instmt_sequence();               ///token是否在语句序列中
void parse_printtree();                         ///输出抽象语法树
void printtree(treenode *lnode);
void printnode(treenode *lnode);
void parse();                                   ///语法分析开始
void gettoken();                                ///获取token
void match(tokentype expectedtoken);            ///匹配
int count_row();                                ///计算token所在行数,主要用与语义分析
int isdtype();                                  ///是否是定义类型
int iscomparison_op();                          ///判断是否是比较运算符

int mainno=0;/**用于判断main函数的个数**/
int ptokenno=0;/**当前记号的计数器。从第0个开始,总是对应当前记号的前一个**/
int printtree_t=0;/**输出语法树的参数**/
treenode *tree_gen;/**语法树的根**/
tokentype dtype[4]= {INT,FLOAT,CHAR,DOUBLE}; /**变量或函数返回值(除VOID以外)的类型**/

///匹配词法中识别的token,并取下一个记号
void match(tokentype expectedtoken)
{

    if(expectedtoken==token)
    {
        gettoken();
    }
    else
    {
        printf("error");
    }
}
/**获得结点**/
void gettoken()
{
    token=token_table[ptokenno].tokenval;
    ptokenno++;
}

///计算记号位于源代码的哪一行
int count_row()
{
    int i;
    for(i=1; i<=lineno; i++)
    {
        if((ptokenno-1)<=line_num_table[i])return i;
    }
}

void parse()
{
    treenode *newtemp=NULL;
    treenode *temp=NULL;
    treenode *gen=NULL;
    treenode *dakuohao;
    gettoken();

    int root_tag=0;  ///用于根节点的判断

    while(ptokenno<tokenno)
    {
        if(isdtype()||(token==STRUCT))
        {
            if(token==INT&&token_table[ptokenno].tokenval == MAIN)
            {
                root_tag++;
                newtemp = newlnodestmt(maink);
                match(INT);
                match(MAIN);
                match(L_XI);
                if(token!=R_XI)
                {
                    newtemp->child[1]=entitypara_list();  ///参数列表
                }
                match(R_XI);
                if(token!=L_DA)
                {
                    printf("error",count_row());
                }
                else
                {
                    newtemp->child[2]=structure_stmt();/**函数实体结构**/
                }
                mainno++;
            }
            else if(token_table[ptokenno].tokenval==ID&&token_table[ptokenno+1].tokenval==L_XI) ///自定义函数
            {
                root_tag++;
                newtemp=newlnodestmt(funck);///动态申请一条语句结构的节点
                match(token);
                treenode *j=newlnodeexp(idk);
                match(ID);
                newtemp->child[0]=j; ///自定义函数名
                match(L_XI);

                if(token!=R_XI)
                {
                    newtemp->child[1]=entitypara_list();  ///参数列表
                }

                match(R_XI);
                if(token!=FENH&&token!=L_DA)
                {
                    printf("error missing&& function error\n");
                }

                else
                {
                    newtemp->child[2]=structure_stmt();
                }

            }
            else if(token==STRUCT&&token_table[ptokenno].tokenval==ID&&token_table[ptokenno+1].tokenval==L_DA)
            {
                root_tag++;
                newtemp=newlnodestmt(structk);
                match(token);
                treenode *j=newlnodeexp(idk);
                match(ID);
                newtemp->child[0]=j;

                if(token==L_DA)
                {
                    newtemp->child[1]=structure_stmt(); ///这里为了简化赋值
                }
            }
            else ///变量声明--全局  if(token==ID)
            {
                root_tag++;
                newtemp=newlnodestmt(defineparak);

                match(token);

                if(token!=ID)
                {
                    printf("变量定义有误\n",count_row());
                }

                newtemp->child[0]=define_assign();

                if(token!=FENH)
                {
                    printf("error ;",count_row);
                }
                else
                    match(token);
            }



            if(temp!=NULL)
                temp->sibling=newtemp;
            temp=newtemp;

            if(root_tag==1)
                gen=temp;
        }

        else
        {
            if(token==ID)
            {
                printf("未定义\n");
            }
            else
            {
                printf("非法188\n");

            }
        }

    }
    if(mainno!=1)
    {
        printf("error\n",count_row());
    }

    tree_gen=gen;
    ///打印抽象语法树
    parse_printtree();
}



/**申请一条语句结构的节点
if for while return assign fun define main define**/
treenode *newlnodestmt(Stmtkind stmt)
{
    /**为新结点初始化**/
    treenode *t=(treenode *)malloc(sizeof(treenode));
    t->nodekind=stmtk;
    t->kind.stmt=stmt;
    t->lineno=count_row();
    int i;
    for(i=0; i<4; i++)
        t->child[i]=NULL;
    t->sibling=NULL;

    if(stmt==maink)/**如果是主函数**/
    {
        t->dtype=token;
    }

    if(stmt==defineparak) /**如果是定义**/
    {
        t->dtype=token;
    }

    if(stmt==funck)
    {
        if(isdtype())
            t->dtype=token;
    }
    return t;
}

///服务于自定义函数的参数  形如 fun(int a,int b)
treenode *entitypara_list()
{
    treenode *t;
    treenode *temp;
    treenode *temp1;
    treenode *newtemp;

    temp=newlnodestmt(defineparak);
    t=temp; ///先把返回的首地址控制住
    if(isdtype())
    {
        match(token);
    }
    else
    {
        printf("error 函数参数有误");
    }

    newtemp=newlnodeexp(idk);
    match(ID);
    temp->child[0]=newtemp;

    while(token==DOUH) /// 不止一个参数时
    {
        match(DOUH);
        temp1=newlnodestmt(defineparak);

        if(isdtype())
        {
            match(token);
        }
        else
        {
            printf("error ");
        }

        newtemp=newlnodeexp(idk);
        match(ID);
        temp1->child[0]=newtemp;
        temp->sibling=temp1;  ///出过bug 注意这里指针的变换
        temp=temp1;
    }

    if(token!=R_XI)
    {
        printf("error !  括号不匹配!!");
    }

    return t;
}

/**
*申请一条算式结构expk的节点,语句内容的类型如下
*opk(+ - * / 还有一些关系操作符),constk,idk
**/
///操作符,常量,标识符(变量名,函数名(idk))
treenode *newlnodeexp(Expkind exp)
{
    ///初始化
    treenode *t=(treenode *)malloc(sizeof(treenode));
    t->nodekind=expk;
    t->kind.exp=exp;
    t->lineno=count_row();
    int i;
    for(i=0; i<4; i++)
    {
        t->child[i]=NULL;
    }

    t->sibling=NULL;

    ///如果为操作符
    if(exp==opk)
    {
        t->attr.op=token;
    }

    ///如果为常量
    if(exp==constk)
    {
        t->attr.val=token_table[ptokenno-1].numval;
    }


    ///如果为变量名、或函数名(标识符)
    if(exp==idk&&token_table[ptokenno].tokenval!=DIAN)
    {
        strcpy(t->attr.name,token_table[ptokenno-1].stringval);
    }


    ///后期加进来的 为struct类型服务
    if(exp=idk&&token_table[ptokenno].tokenval==DIAN)
    {
        char struct_temp1[100]= {'\0'};
        //char struct_temp2[100]= {'\0'};
        char struct_temp3[100]= {'\0'};
        char struct_temp4[100]= {'\0'};
        strcpy(struct_temp1,token_table[ptokenno-1].stringval);
        //strcpy(struct_temp2,token_table[ptokenno].stringval);
        strcpy(struct_temp3,token_table[ptokenno+1].stringval);
        int i=0,j=0;
        while(struct_temp1[j]!='\0')
        {
            struct_temp4[i]=struct_temp1[j];
            i++;
            j++;
        }
        struct_temp4[i]='.';
        i++;
        j=0;
        while(struct_temp3[j]!='\0')
        {
            struct_temp4[i]=struct_temp3[j];
            i++;
            j++;
        }
        strcpy(t->attr.name,struct_temp4);
    }
    return t;
}


/***********************************************************
* 功能:以大括号开始的一个大结构
        比如: for if  while  main fun
**********************************************************/
treenode *structure_stmt()
{
    treenode *t=NULL;
    treenode *temp=NULL;
    treenode *newtemp;
    int k=0;
    match(L_DA);
    while(isin_first_instmt_sequence())/**当前Token是否在instmt-sequence的定义集合里**/
    {
        k++;
        newtemp=instmt_sequence();  ///开始各自的语句

        if(temp!=NULL)
        {
            temp->sibling=newtemp;
        }

        temp=newtemp;
        if(k==1)
        {
            t=temp; ///把头结点固定住 以便返回
        }
    }
    match(R_DA);
    return t;
}
///为了判断是不是这些语句比如 for if while 定义 返回
int isin_first_instmt_sequence()
{
    tokentype first_instmt[20]= {FOR,WHILE,IF,INT,FLOAT,
                                 CHAR,DOUBLE,ID,RETURN,
                                 STRUCT,SWITCH,CASE,BREAK,
                                    DEFAULT};
    int i=0;
    for(i=0; i<20; i++)
    {
        if(token==first_instmt[i])
            return 1;
    }
    return 0;
}


/**FOR IF WHILE 定义 PRINTF SCANF语句 RETURN 等等**/
treenode *instmt_sequence()
{
    treenode *t=NULL;

    switch (token)
    {
    /**for循环 !!**/
    case FOR :
    {
        t=for_stmt();
        break;
    }
    /**IF语句 !!**/
    case IF :
    {
        t=if_stmt();
        break;
    }
    /**while语句 !!**/
    case WHILE :
    {
        t=while_stmt();
        break;
    }
    /**struct语句 !!**/
    case SWITCH:
    {
        t=switch_stmt();
        break;
    }
     /**case语句 !!**/
    case CASE:
    {
       t=case_stmt();
       break;
    }
     /**case语句 !!**/
    case BREAK:
    {
       t=break_stmt();
       break;
    }
    case DEFAULT:
    {
       t=default_stmt();
       break;
    }
    default:
    {
        t=statement(); ///  普通语句有很多--函数调用,定义,赋值 return等等
        if(token!=FENH)
        {
            printf("missing ';' %d ",count_row());///如果为定义语句;打印;输入语句,则后面判断有没有分号
        }
        else
        {
            match(FENH);
        }
        break;
    }
    }
    return t;
}


///for语句
treenode *for_stmt()
{
    treenode *t=NULL;
    treenode *temp;

    t=newlnodestmt(fork);

    match(FOR);
    match(L_XI);

    if(token!=FENH)
    {
        if(token==INT)
        {
            t->child[0]=definepara_stmt();
        }
        else
        {
            t->child[0]=exp2();
        }
    }

    match(FENH);
    if(token!=FENH)
    {
        if(token_table[ptokenno].tokenval==EQUAL)
        {
            printf("warning!! 不能为赋值等式");
        }
        else
        {
            t->child[1]=exp2();
        }
    }

    match(FENH);

    if(token!=R_XI)
    {
        t->child[2]=exp2();
    }

    match(R_XI);

    if(token==FENH)
    {
        match(FENH);
        return t;
    }

    t->child[3]=structure_stmt();
    return t;
}

int ifelse_tag=0;
treenode* if_stmt()
{
    treenode *t;
    t=newlnodestmt(ifk);
    match(IF);
    match(L_XI);
    if(token_table[ptokenno].tokenval==EQUAL&&token_table[ptokenno+1].tokenval!=EQUAL)
    {
        printf("warning");
    }
    t->child[0]=BUER_stmt();
    match(R_XI);
    t->child[1]=structure_stmt();

    if(token==ELSE&&token_table[ptokenno].tokenval==IF)
    {
        match(ELSE);
        t->child[2]=if_stmt();
        ifelse_tag=1;
    }
    if(token==ELSE&&token_table[ptokenno].tokenval!=IF)
    {
        match(ELSE);
        t->child[2]=structure_stmt();
    }

    return t;
}
treenode *BUER_stmt()
{
    treenode *t;
    treenode *t1;
    treenode *t2;
    if(token_table[ptokenno+2].tokenval==ADE || token_table[ptokenno+3].tokenval==ADE||
       token_table[ptokenno+2].tokenval==HUO ||token_table[ptokenno+3].tokenval==HUO)
    {
    }
    else
    {
        t=exp2();
    }
}
///主要用于FOR ,IF while ,你不知道是赋值还是关系运算。
treenode *exp2()
{
    treenode *t;
    if(token==ID&&token_table[ptokenno].tokenval==EQUAL)
    {
        t=assign_stmt();
    }
    else
    {
        t=exp();
    }
    return t;
}

/***********************************************************
 * 功能:	while语句
 **********************************************************/
treenode *while_stmt()
{
    treenode *t=newlnodestmt(whilek);
    match(WHILE);
    match(L_XI);
    t->child[0]=exp2();
    match(R_XI);
    if(token==L_DA)
        t->child[1]=structure_stmt();
    return t;///!!!这个bug 找了好久呀!!!
}
/***********************************************************
 * 功能:	switch语句
 **********************************************************/
treenode *switch_stmt()
{
    treenode *t=newlnodestmt(switchk);
    match(SWITCH);
    match(L_XI);
    t->child[0]=exp2();
    match(R_XI);
    if(token==L_DA)
    {
        t->child[1]=structure_stmt();
    }
    return t;
}
///用于case语句段
treenode *case_stmt()
{
    treenode *t=newlnodestmt(casek);
    match(CASE);
    treenode *j=newlnodeexp(idk);
    t->child[0]=j;
    match(ID);
    match(MAOH);
    if(token==L_DA)
    {
        t->child[1]=structure_stmt();
    }
    return t;
}
///用于break语句
treenode *break_stmt()
{
    treenode *t=newlnodestmt(breakk);
    match(BREAK);
    match(FENH);
    return t;
}
///用于default语句
treenode *default_stmt()
{
    treenode *t=newlnodestmt(defaultk);
    match(DEFAULT);
    match(MAOH);
    if(token==L_DA)
    {
        t->child[0]=structure_stmt();
    }
    return t;
}
treenode *statement()
{
    treenode *t=NULL;
    /**如果是dtype,则为定义语句**/
    if(isdtype())
    {
        t=definepara_stmt();
    }
    else if(token==RETURN)
    {
        t=newlnodestmt(returnk);
        match(RETURN);
        t->child[0]=exp();
    }
    else if(token==STRUCT)
    {
        t=definepara_stmt();
    }
    else if(token==ID)  /**函数调用,数组定义,变量的赋值**/
    {
        int tag_array=array_judge(ptokenno);

        if(token_table[ptokenno].tokenval==EQUAL||tag_array==1)
        {
            t=assign_stmt();///数组或变量赋值(变量可能为函数调用的结果)
        }
        else if(token_table[ptokenno].tokenval==L_XI)
        {
            t=fun_apply();  /// 函数调用
        }
        else if(token_table[ptokenno].tokenval==DIAN&&token_table[ptokenno+2].tokenval==EQUAL)
        {
            t=assign_stmt();
        }
        else ///if()待写  感觉不用条件
        {
            t=exp();
        }

    }
    return t;
}
/***********************************************************
 * 功能:	函数调用  fun(a,b)
 **********************************************************/
treenode *fun_apply()
{
    treenode *t;
    t=newlnodestmt(funck);
    treenode *temp1=newlnodeexp(idk);
    match(ID);
    match(L_XI);
    treenode *temp2=input_para_list();
    t->child[0]=temp1;
    t->child[1]=temp2;
    match(R_XI);
    return t;
}

///参数列表 服务于函数调用里的参数 比如fun(1,2)
treenode *input_para_list()
{
    treenode *t;
    treenode *temp;
    temp=factor();
    t=temp;
    while(token==DOUH)
    {
        match(DOUH);
        temp->sibling=factor();
        temp=temp->sibling;
    }
    return t;
}
int array_judge(int p)
{
    if(token_table[p].tokenval==L_ZH)
    {
        int i;
        for(i=p+1; i<1000; i++) ///有bug!!。。。
        {
            if(token_table[i].tokenval==R_ZH)
            {
                return 1;
            }
        }
        return -1;
    }
    return -1;
}

/**判断当前记号是否是变量或函数返回值(除VOID以外)**/
int isdtype()
{
    int i=0;
    for(; i<4; i++)
    {
        if(token==dtype[i])
            return 1;
    }
    return 0;
}


/**定义语句**/
treenode *definepara_stmt()
{
    treenode *t=NULL;
    t=newlnodestmt(defineparak);

    if (isdtype())
    {
        match(token);//dtype
    }
    else if(token==STRUCT)
    {
        match(token);
        match(ID);  ///把整个struct XX match掉
    }

    else
        printf("arguement has no type", count_row());

    t->child[0]=define_assign();
    return t;
}


/**变量赋值定义  数组的定义,初始化,初始化和定义的同时进行**/
treenode *define_assign()
{
    treenode *t=NULL;
    treenode *temp=NULL;
    treenode *newtemp;
    int k=0;


    if(token_table[ptokenno].tokenval==FENH)
    {
        k++;
        newtemp=newlnodeexp(idk);
        match(ID);
        //match(FENH);
        return t=newtemp;
    }
    /**支持变量定义初始化,连续定义等**/
    while (token_table[ptokenno].tokenval == EQUAL || token_table[ptokenno].tokenval == DOUH
            || token_table[ptokenno].tokenval == FENH||token_table[ptokenno].tokenval==L_ZH)

    {
        switch (token_table[ptokenno].tokenval)
        {

        case EQUAL:  /**赋值语句**/
        {
            k++;
            newtemp=assign_stmt();
            if(temp!=NULL)
            {
                temp->sibling=newtemp;
            }
            temp=newtemp;
            if(token==DOUH)
            {
                match(DOUH);
            }
            if(k==1)
            {
                t=temp;
            }
            break;
        }
        case DOUH:
        {
            k++;
            newtemp=newlnodeexp(idk);
            match(ID);
            match(DOUH);
            if(temp!=NULL)
            {
                temp->sibling=newtemp;
            }
            temp=newtemp;
            if(k==1)
            {
                t=temp;
            }
            break;
        }

        case FENH:
        {
            k++;
            newtemp=newlnodeexp(idk);
            match(ID);
            if(temp!=NULL)
            {
                temp->sibling=newtemp;
            }
            temp=newtemp;
            if(k==1)
            {
                t=temp;
            }
            break;
        }
        case L_ZH:  ///数组部分!!
        {
            k++;

            newtemp=newlnodestmt(define_arrayk);
            treenode *t1=newlnodeexp(idk);
            match(ID);
            newtemp->child[0]=t1;

            match(L_ZH);
            if(token!=NUM&&token!=R_ZH)  ///一些语义分析
            {
                printf("error!!数组定义有误");
            }
            if(token==NUM)
            {
                treenode *t2=newlnodeexp(constk);
                match(NUM);
                newtemp->child[1]=t2;
            }
            match(R_ZH);
            if(temp!=NULL)
            {
                temp->sibling=newtemp;
            }
            temp=newtemp;
            if(token==DOUH)
            {
                match(DOUH);
            }
            if(k==1)
            {
                t=temp;
            }
            break;
        }
        default:
        {
            printf("there should be assignment statement or variable",count_row());
        }
        }
    }
    return t;
}


/**赋值语句  数组的赋值后期加进来!!!!**/
treenode *assign_stmt()
{
    treenode *t1;
    if(token_table[ptokenno].tokenval==L_ZH) ///数组赋值  形如a[1] a[2]
    {
        t1=newlnodeexp(cite_arrayk);
        treenode *t2=newlnodeexp(idk);
        match(ID);
        t1->child[0]=t2;
        match(L_ZH);
        t1->child[1]=exp2(); ///直接是factor里的数字结构了;
        match(R_ZH);
    }
    else if(token_table[ptokenno].tokenval==DIAN)  ///为struct结构专门定义
    {
        t1 = newlnodeexp(idk);
        match(ID);
        match(DIAN);
        match(ID);
    }
    else
    {
        t1=newlnodeexp(idk);
        match(ID);
    }
    match(EQUAL);///不需要将=匹配成op

    ///opk=EQUAL
    treenode *t=newlnodestmt(assignk);
    t->child[0]=t1;
    t->child[1]=exp();
    return t;
}


///  simple_exp conpare simple_exp   ||simple_exp
treenode *exp()
{
    treenode *t;
    treenode *temp;

    temp=simple_exp();
    ///简单表达式
    if(iscomparison_op())
    {
        t=newlnodeexp(opk);
        match(token);
        t->child[0]=temp;
        t->child[1]=simple_exp();
    }
    else
    {
        t=temp;
    }

    return t;
}

int iscomparison_op()
{
    tokentype compare_op[6]= {SMALLER,SMALLEREQU,
                              BIGGER,BIGGEREQU,
                              NOTEQU,IFEQU
                             } ;//< <= > >= != ==
    int i;
    for(i=0; i<6; i++)
    {
        if(token==compare_op[i])
        {
            return 1;
        }
    }
    return 0;///没有匹配上
}

///简单表达式 加减
treenode *simple_exp()
{
    treenode *t=NULL;
    treenode *newtemp;
    treenode *temp;

    temp=term();

    ///加法或减法语句
    while(token==PLUS||token==MINUS)
    {
        newtemp=newlnodeexp(opk);
        match(token);
        ///子节点分别为左右两个term
        newtemp->child[0]=temp;
        newtemp->child[1]=term();
        temp=newtemp;
    }
    t=temp;
    return t;
}

///主要是乘除
treenode *term()
{
    treenode *t=NULL;
    treenode *temp;
    treenode *newtemp;

    temp=factor();

    while(token==TIMES||token==DIVIDE)
    {
        newtemp=newlnodeexp(opk);
        match(token);
        newtemp->child[0]=temp;
        newtemp->child[1]=factor();
        temp=newtemp;
    }

    return t=temp;
}

///最基本的单模块
treenode *factor()
{
    treenode *t=NULL;
    switch (token)
    {
    ///带括号的表达式
    case L_XI:
    {
        match(L_XI);
        t=exp();
        match(R_XI);
        break;
    }

    ///变量---可能为函数调用语句,可能为数组,可能为普通变量
    case ID:
    {
        if(token_table[ptokenno].tokenval==L_XI)  ///函数调用
        {
            t=fun_apply();
        }
        else if(token_table[ptokenno].tokenval==L_ZH) ///数组
        {
            t=newlnodeexp(cite_arrayk);
            treenode *temp1=newlnodeexp(idk);
            match(ID);
            match(L_ZH);
            treenode *temp2=exp2() ;  ///可缩小范围factor 即可;
            t->child[0]=temp1;
            t->child[1]=temp2;
            match(L_ZH);
        }
        else   ///普通变量
        {
            t = newlnodeexp(idk);
            match(ID);
        }
        break;
    }

    ///数字
    case NUM:
    {
        t=newlnodeexp(constk);
        t->attr.val=token_table[ptokenno-1].numval;
        match(NUM);
        break;
    }
    }
    return t;
}









/** ** **** **** *****   *******       输出抽象语法树的过程  *******   *****  ******   *****/

void parse_printtree()
{
    treenode *t=tree_gen;
    printtree(t);
}


///树
void printtree(treenode *lnode)
{
    int i;
    treenode *pnode;
    int TAG=printtree_t;
    for(i=0; i<TAG; i++)
        printf("        ");
    printnode(lnode);
    printf("\n");
    printtree_t++;
    for(i=0; i<4; i++)
        if(lnode->child[i]!=NULL)
        {
            pnode=lnode;
            lnode=lnode->child[i];
            printtree(lnode);
            printtree_t--;
            lnode=pnode;
        }
    if(lnode->sibling!=NULL)
    {
        lnode=lnode->sibling;
        printtree_t=TAG;
        printtree(lnode);
    }
}
///打印结点
void printnode(treenode *lnode)
{
    if(lnode->nodekind==expk) ///表达式结点
    {

        switch (lnode->kind.exp)
        {
        case idk:
        {
            printf("id=  [%s]",lnode->attr.name);
            break;
        }
        case opk:
        {
            token=lnode->attr.op;
            printf("op=  [%s]",tokenstring());///tokenstring()不需要参数
            break;
        }
        case constk:
        {
            printf("num=  [%g]",lnode->attr.val);
            break;
        }
        case cite_arrayk:
        {
            printf("array_id'[%s]'",lnode->child[0]->attr.name);
            break;
        }

        }
    }
    else if(lnode->nodekind==stmtk) ///stmtk  //函数结点
    {
        switch(lnode->kind.stmt)
        {
        case ifk:
        {
            printf("[if]");
            break;
        }
        case fork:
        {
            printf("[for]");
            break;
        }
        case whilek:
        {
            printf("[while]");
            break;
        }

        case returnk:
        {
            printf("[return]");
            break;
        }
        case assignk:
        {
            printf("assign:");
            break;
        }
        case funck:
        {
            token=lnode->dtype;
            if(lnode->child[2]!=NULL)
            {
                printf("function : type is");
                printf(" [%s]",tokenstring());
            }
            else
            {
                printf("callfunc :");
            }

            break;
        }
        case defineparak:
        {
            token=lnode->dtype;
            printf("definepara : ");
            printf("[%s]",tokenstring());
            break;
        }
        case maink:
        {
            printf("[main]");
            break;
        }
        case define_arrayk:
        {
            printf("definearray");
            break;
        }
        case structk:
        {
            printf("[struct]");
            break;
        }
        case casek:
        {
            printf("[case]");
            break;
        }
        case breakk:
        {
            printf("[break]");
            break;
        }
        case switchk:
        {
            printf("[switch]");
            break;
        }

        case defaultk:
        {
            printf("[default]");
            break;
        }
        default:
            printf("error1!!!");
        }
    }
    else
    {
        printf("节点有误!!");
    }
}
//tac.c
#include"global.h"
#include"TAC.h"
char *opkinds_string(opkinds op);///这个在优化还要用,所以不能私有化
static void start_tac(treenode* lnode);
static char *deal_expk(treenode* lnode);  ///处理算术表达式
static void MAIN_K(treenode *lnode);      ///处理main
static void DEFINEPARA_K(treenode *lnode); ///处理定义结点
static void ASSIGN_K(treenode *lnode);    ///处理赋值结点
static void RETURN_K(treenode *lnode);      ///处理return结点
static void IF_K(treenode *lnode);          ///处理if结点
static void WHILE_K(treenode *lnode);       ///处理while结点
static void FOR_K(treenode *lnode);         ///处理for结点
static void FUNC_K(treenode *lnode);        ///处理函数调用结点
static void get_tac(opkinds op,char a[],char b[],char c[]); ///产生四元式
static char * newlabel();     ///申请跳转label
static char * newtemp();      ///申请个临时寄存器
fourvarcode *tac_temp;     ///四元式链表的一个变量指针
fourvarcode *tac_head;     ///四元式的链表头指针
static int newtemp_no=0;    ///中间变量的寄存器的计数器
static int newlabel_no=0;  ///跳转标志的计数器
static char adr[10]= {'\0'};
static char empty[10]= "\0";
void  tac()
{
    tac_head=(fourvarcode*)malloc(sizeof(fourvarcode));
    tac_temp=tac_head;
    treenode *lnode=tree_gen;

    start_tac(lnode);

	print_tac();
}


void start_tac(treenode* lnode)
{
    while(lnode!=NULL)
    {
        if(lnode->nodekind==stmtk) ///是语句节点(比如:if while main  等等)
        {
            if(lnode->kind.stmt==maink)
            {
                MAIN_K(lnode);
            }
            if(lnode->kind.stmt==defineparak)
            {
                DEFINEPARA_K(lnode);
            }
            if(lnode->kind.stmt==assignk)
            {
                ASSIGN_K(lnode);
            }
            if(lnode->kind.stmt==returnk)
            {
                RETURN_K(lnode);
            }
            if(lnode->kind.stmt==ifk)
            {
                IF_K(lnode);
            }
            if(lnode->kind.stmt==whilek)
            {
                WHILE_K(lnode);
            }
            if(lnode->kind.stmt==fork)
            {
                FOR_K(lnode);
            }
            if(lnode->kind.stmt==funck)
            {
                FUNC_K(lnode);
            }
        }
        lnode=lnode->sibling;
    }
}


///处理main节点
void MAIN_K(treenode *lnode)
{

    char a[10];
    a[0]='0';
    a[1]='\0';
    get_tac(mainfuns,adr,adr,adr); ///加了main开始的标志

    if(lnode->child[1]!=NULL)  ///main函数中有参数
    {
        token=lnode->child[1]->dtype;
        strcpy(a,tokenstring());
        get_tac(defineparas,a,lnode->child[1]->child[0]->attr.name,adr);
        treenode *t;
        t=lnode->child[1]->sibling;

        while(t!=NULL)
        {
            token=t->dtype;
            strcpy(a,tokenstring());
            get_tac(defineparas,a,t->child[0]->attr.name,adr);
            t=t->sibling;
        }
    }
    start_tac(lnode->child[2]);  ///递归--进入main结构
    get_tac(mainfuns_end,adr,adr,adr);
}

///处理define 语句
void DEFINEPARA_K(treenode *lnode)
{
    treenode *t;
    token=lnode->dtype;
    char a[10];
    strcpy(a,tokenstring()); ///存储变量类型
    t=lnode->child[0];
    while(t!=NULL)///后期考虑数组!!!!!!
    {
        if(t->kind.stmt==assignk)  ///定义+变量赋值
        {
            get_tac(defineparas,a,t->child[0]->attr.name,adr);
            start_tac(t);
        }

        else if(t->kind.stmt==define_arrayk)  ///数组!!未完成!!
        {
            char b[10];
            sprintf(b,"%f",t->child[1]->attr.val);
        }

        else  ///变量定义
        {
            get_tac(defineparas,a,t->attr.name,adr);
        }

        t=t->sibling;  ///可能有连续定义--所以要搜寻一下它的兄弟节点
    }
}


///处理赋值节点
void ASSIGN_K(treenode *lnode)
{
    char t1[10],t2[10];
    strcpy(t1,newtemp());
    strcpy(t2,deal_expk(lnode->child[1]));  ///一定要处理assign等式右边的
    get_tac(asns,t2,t1,adr);
    if(lnode->child[0]->kind.exp==idk)
    {
        get_tac(asns,t1,lnode->child[0]->attr.name,adr); ///将值给id
    }
   /* else ///if(lnode->child[0]->kind.exp==cite_arrayk 是数组的话--
    {
        char t3[10];
        strcpy(t3,deal_expk(lnode->child[0]));
        get_tac(asns,t1,t3,adr);
    }*/
}

///处理return节点
void RETURN_K(treenode *lnode)
{
    char t1[10],t2[10];
    if(lnode->child[0]!=NULL)
    {
        strcpy(t1,newtemp());
        strcpy(t2,deal_expk(lnode->child[0]));
        get_tac(asns,t2,t1,adr);
        get_tac(returns,t1,adr,adr);
    }
    else
    {
        get_tac(returns,adr,adr,adr);
    }
}

///处理 if节点
void IF_K(treenode *lnode)
{
    get_tac(ifstarts,adr,adr,adr);  ///if的开始四元式
    char t1[10],t2[10],t3[10];  ///寄存器数组
    char L1[10],L2[10];      ///跳转临时数组
    char a[10];

    strcpy(t1,newtemp()); ///申请寄存器
    if(lnode->child[0]->kind.exp==opk)///一定要为关系表达式,不然就有问题 opk为关系操作
    {
        strcpy(t2,deal_expk(lnode->child[0]));
    }

    get_tac(asns,t2,t1,adr);
    strcpy(L1,newlabel());///申请个跳走lable

    get_tac(if_fs,t1,L1,adr);  ///如果布尔表达式为假,直接跳走
    start_tac(lnode->child[1]);///进去if的执行结构

    strcpy(L2,newlabel());  ///if执行完就跳出循环了
    get_tac(jumps,L2,adr,adr);

    get_tac(labss,L1,adr,adr);///if错了之后 跳过来的位置
    start_tac(lnode->child[2]);///递归解决else if (else)结构

    get_tac(labss,L2,adr,adr);
    get_tac(ifends,adr,adr,adr);
}

void WHILE_K(treenode *lnode)
{
    char t1[10],t2[10],t3[10];
    char L1[10],L2[10],L3[10];
    strcpy(L1,newlabel());
    get_tac(labss,L1,adr,adr); ///不同于if语句 while是符合条件则一直循环,所以提前设置好跳转位置
    get_tac(whilestarts,adr,adr,adr);

    strcpy(t1,newtemp());

    if(lnode->child[0]->kind.exp==opk)  ///while里面都应该为布尔表达式
    {
        strcpy(t2,deal_expk(lnode->child[0]));
    }
    get_tac(asns,t2,t1,adr);

    strcpy(L2,newlabel());
    get_tac(if_fs,t1,L1,adr);

    start_tac(lnode->child[1]); ///进入while结构进行递归

    get_tac(whileends,adr,adr,adr);
    get_tac(jumps,L1,adr,adr); ///继续执行

    get_tac(labss,L2,adr,adr);
}


void FOR_K(treenode *lnode)
{
    char t1[10],t2[10],t3[10];
    char L1[10],L2[10],L3[10];
    start_tac(lnode->child[0]);  ///第一个是赋值语句,递归解决

    strcpy(L1,newlabel());
    get_tac(labss,L1,adr,adr);
    get_tac(forstarts,adr,adr,adr);

    if(lnode->child[1]!=NULL)
    {
        strcpy(t1,newtemp());
        if(lnode->child[1]->kind.exp==opk) ///中间一部分布尔表达式
        {
            strcpy(t2,deal_expk(lnode->child[1]));
        }
        get_tac(asns,t2,t1,adr);
    }

    strcpy(L2,newlabel());
    get_tac(for_cmp,t1,L2,adr);

    start_tac(lnode->child[3]); ///for循环要先执行循环,再执行for中的第三条语句
    start_tac(lnode->child[2]);

    get_tac(forends,adr,adr,adr);
    get_tac(jumps,L1,adr,adr);
    get_tac(labss,L2,adr,adr);
}



void FUNC_K(treenode *lnode)
{
    if(lnode->child[2]==NULL) ///为函数调用
    {
        char t1[10],t2[10];
        char para_num[10];

        if(lnode->child[1]!=NULL) ///有参数
        {
            sprintf(para_num,"%d",count_para(lnode->child[1]));
        }
        else
        {
            para_num[0]='0';
            para_num[1]='\0'; ///做个标记,参数为空
        }
        get_tac(begin_args,para_num,adr,adr);

        if(lnode->child[1]!=NULL)
        {
            strcpy(t1,newtemp());
            strcpy(t2,deal_expk(lnode->child[1]));
            get_tac(asns,t2,t1,adr);
            get_tac(args,t1,adr,adr);
            treenode *t;
            t=lnode->child[1]->sibling;
            while(t!=NULL)
            {
                strcpy(t1,newtemp());
                strcpy(t2,deal_expk(t));
                get_tac(asns,t2,t1,adr);
                get_tac(args,t1,adr,adr);
                t=t->sibling;
            }
        }
        get_tac(callfuns,lnode->child[0]->attr.name,adr,adr);
    }
    else  ///自定义的函数结构
    {
        char a[10];
        if(lnode->child[1]!=NULL)
        {
            sprintf(a,"%d",count_para(lnode->child[1]));
        }
        else
        {
            a[0]='0';
            a[1]='\0';
        }

        get_tac(definefuns,lnode->child[0]->attr.name,a,adr);
        if(lnode->child[1]!=NULL)  ///解决fun(括号里的函数定义)
        {
            token=lnode->child[1]->dtype;
            strcpy(a,tokenstring());
            get_tac(defineparas,a,lnode->child[1]->child[0]->attr.name,adr);
            treenode *t;
            t=lnode->child[1]->sibling;
            while(t!=NULL)
            {
                token=t->dtype;
                strcpy(a,tokenstring());
                get_tac(defineparas,a,t->child[0]->attr.name,adr);
                t=t->sibling;
            }
        }
        start_tac(lnode->child[2]);
        get_tac(definefuns_end,lnode->child[0]->attr.name,adr,adr);
    }
}


void get_tac(opkinds op,char a[],char b[],char c[])
{
    fourvarcode* t=NULL;
    t=(fourvarcode*)malloc(sizeof(fourvarcode));
    t->op=op;

    if(a[0]=='\0')
    {
        t->addr1.kind=emptys;
        strcpy(t->addr1.name,"\0");
    }
    else if((a[0]>='a'&&a[0]<='z')||(a[0]>='A'&&a[0]<='Z'))
    {
        t->addr1.kind=strings;
        strcpy(t->addr1.name,a);
    }
    else
    {
        t->addr1.kind=consts;
        strcpy(t->addr1.name,a);
    }


    if(b[0]=='\0')
    {
        t->addr2.kind=emptys;
        strcpy(t->addr2.name,"\0");
    }
    else if((b[0]>='a'&&b[0]<='z')||(b[0]>='A'&&b[0]<='Z'))
    {
        t->addr2.kind=strings;
        strcpy(t->addr2.name,b);
    }
    else
    {
        t->addr2.kind=consts;
        strcpy(t->addr2.name,b);
    }


    if(c[0]=='\0')
    {
        t->addr3.kind=emptys;
        strcpy(t->addr3.name,"\0");
    }
    else if((c[0]>='a'&&c[0]<='z')||(c[0]>='A'&&c[0]<='Z'))
    {
        t->addr3.kind=strings;
        strcpy(t->addr3.name,c);
    }
    else
    {
        t->addr3.kind=consts;
        strcpy(t->addr3.name,c);
    }

 printf("(");
    printf("%s ,",opkinds_string(t->op));
    if(t->addr1.kind==emptys)
        printf("_ ,");
    else
        printf("%s ,",t->addr1.name);

    if(t->addr2.kind==emptys)
        printf("_ ,");
    else
        printf("%s ,",t->addr2.name);

    if(t->addr3.kind==emptys)
        printf("_ ,");
    else
        printf("%s ,",t->addr3.name);
    printf(")");
    printf("\n");

    t->next=NULL;
    tac_temp->next=t;
    tac_temp=t;
}
///中间变量,在汇编中是存在寄存器中
char *newtemp()
{
    char s[10];
    sprintf(s,"t#%d",newtemp_no);
    newtemp_no++;
    return s;
}

char* deal_expk(treenode *lnode)///专门处理expk的式子
{
    char empty[10];
    empty[0]='\0';
    while(lnode!=NULL)
    {
        switch(lnode->kind.exp)
        {
        case opk:
        {
            char t2[10],t3[10],t4[10],a[10],b[10];
            strcpy(t2,newtemp());
            strcpy(t3,newtemp());

            if(lnode->child[1]->kind.exp==constk)
            {
                char c[10];
                sprintf(c,"%d",lnode->child[1]->attr.val);
                if((lnode->attr.op==PLUS||lnode->attr.op==MINUS)&&strcmp(c,"1")==0)
                {
                    if (lnode->child[0]->sibling!=NULL)///如果只是a+1的运算 先不考虑
                        printf("error");
                }
            }
            strcpy(a,deal_expk(lnode->child[0]));
            strcpy(b,deal_expk(lnode->child[1]));
            switch (lnode->attr.op)
            {
            case PLUS:///+
            {
                get_tac(asns,a,t2,empty);
                    ///表达式形如 a=b+7,需要从内存中取数
                if(b[1]!='#')
                {
                    get_tac(asns,b,t3,empty);
                    strcpy(t4,newtemp());
                    get_tac(adds,t2,t3,t4);
                }
                else   ///不需要从内存中取数
                {
                    strcpy(t4,newtemp());
                    get_tac(adds,t2,b,t4);
                }
                return t4;
            }

            case MINUS:///-
            {
                get_tac(asns,a,t2,empty);
                if(b[1]!='#')
                {
                    get_tac(asns,b,t3,empty);
                    strcpy(t4,newtemp());
                    get_tac(minus,t2,t3,t4);
                }
                else
                {
                    strcpy(t4,newtemp());
                    get_tac(minus,t2,b,t4);
                }
                return t4;
            }

            case TIMES: ///乘
            {
                get_tac(asns,a,t2,empty); //取a值到t2
                get_tac(asns,b,t3,empty);//取b值到t3
                strcpy(t4,newtemp()); //生成一个新的符号t4
                get_tac(muls,t2,t3,t4);// t4=t2*t3
                return t4;
            }
            case DIVIDE:  ///除
            {
                get_tac(asns,a,t2,empty);
                get_tac(asns,b,t3,empty);
                strcpy(t4,newtemp());
                get_tac(divs,t2,t3,t4);
                return t4;
            }
            case MODE:  ///取模
            {
                get_tac(asns,a,t2,empty);
                get_tac(asns,b,t3,empty);
                strcpy(t4,newtemp());
                get_tac(mods,t2,t3,t4);
                return t4;
            }
            case NOTEQU: ///!=
            {
                get_tac(asns,a,t2,empty);
                get_tac(asns,b,t3,empty);
                strcpy(t4,newtemp());
                get_tac(not_eqs,t2,t3,t4);
                return t4;
            }
            case IFEQU:///==
            {
                get_tac(asns,a,t2,empty);
                get_tac(asns,b,t3,empty);
                strcpy(t4,newtemp());
                get_tac(if_eqs,t2,t3,t4);
                return t4;
            }
            case SMALLER: ///<
            {
                get_tac(asns,a,t2,empty);
                get_tac(asns,b,t3,empty);
                strcpy(t4,newtemp());
                get_tac(smas,t2,t3,t4);
                return t4;
            }
            case SMALLEREQU:///<=
            {
                get_tac(asns,a,t2,empty);
                get_tac(asns,b,t3,empty);
                strcpy(t4,newtemp());
                get_tac(sma_eqs,t2,t3,t4);
                return t4;
            }
            case BIGGER:///>
            {
                get_tac(asns,a,t2,empty);
                get_tac(asns,b,t3,empty);
                strcpy(t4,newtemp());
                get_tac(bigs,t2,t3,t4);
                return t4;
            }
            case BIGGEREQU:///>=
            {
                get_tac(asns,a,t2,empty);
                get_tac(asns,b,t3,empty);
                strcpy(t4,newtemp());
                get_tac(big_eqs,t2,t3,t4);
                return t4;
            }

            }
        }
        case constk:///为常量
        {
            char t6[10];
            sprintf(t6,"%g",lnode->attr.val);
            return t6;
        }
        case idk:  ///如果为变量
        {

            return lnode->attr.name;
        }
        case funck:///函数调用
        {
            char t5[10],t6[10],a[10];
            if(lnode->child[1]!=NULL)
            {
                sprintf(a,"%d",count_para(lnode->child[1]));
            }
            else
            {
               a[0]='0',a[1]='\0';
            }
            get_tac(begin_args,a,empty,empty);
            if(lnode->child[1]!=NULL)
            {
                strcpy(t5,newtemp());
                strcpy(t6,deal_expk(lnode->child[1]));///没有走t->sibling
                get_tac(asns,t6,t5,empty);
                get_tac(args,t5,empty,empty);
                treenode *t;
                t=lnode->child[1]->sibling;
                while(t!=NULL)
                {
                    strcpy(t5,newtemp());
                    strcpy(t6,deal_expk(t));
                    get_tac(asns,t6,t5,empty);
                    get_tac(args,t5,empty,empty);
                    t=t->sibling;
                }
            }
            get_tac(callfuns,lnode->child[0]->attr.name,empty,empty);

            char t7[10];
            get_tac(funreturns,lnode->child[0]->attr.name,empty,empty);
            strcpy(t7,newtemp());
            return t7;

        }
        }
    }
}
char *newlabel()
{
    char s[10];
    sprintf(s,"L%d",newlabel_no);
    newlabel_no++;
    return s;
}

int count_para(treenode *lnode)
{
    treenode *t=lnode->sibling;
    int count=1;
    while(t!=NULL)
    {
        count++;
        t=t->sibling;
    }
    return count;
}



/*************************输出四元式*************************/

void print_tac()
{
	fourvarcode* t=tac_head->next;
	while(t!=NULL)
	{
	    if(t->op==ifstarts||t->op==ifends||t->op==mainfuns_end||t->op==mainfuns||t->op==forstarts||t->op==forends||t->op==defineparas
            ||t->op==whilestarts ||t->op==whileends)
        {
            t=t->next;
        }
        else
        {
	    printf("(");
		printf("%s ,",opkinds_string(t->op));
		if(t->addr1.kind==emptys)
			printf("_ ,");
		else
			printf("%s ,",t->addr1.name);

		if(t->addr2.kind==emptys)
			printf("_ ,");
		else
			printf("%s ,",t->addr2.name);

		if(t->addr3.kind==emptys)
			printf("_ ,");
		else
			printf("%s ,",t->addr3.name);

		t=t->next;
		printf(")");
		printf("\n");
        }
	}
}




///转换为字符型,符号表
char *opkinds_string(opkinds op)
{
    switch (op)
    {
    case (if_fs):
        return "if_f"; ///if_false
    case (asns):
        return "=";  ///赋值
    case (labss):
        return "lab";
    case (muls):
        return "*";
    case (adds):
        return "+";
    case (minus):
        return "-";
    case (callfuns):
        return "callfun";
    case (definefuns):
        return "definefun";
    case (mainfuns):
        return "mainfun";
    case (divs):
        return "/";
    case (if_eqs):
        return "==";
    case (not_eqs):
        return "!=";
    case (bigs):
        return ">";
    case (big_eqs):
        return ">=";
    case (smas):
        return "<";
    case (sma_eqs):
        return "<=";
    case (returns):
        return "return";
    case (jumps):
        return "jump";
    case (args):
        return "arg";
    case (begin_args):
        return "begin_arg";
    case(mainfuns_end):
        return "mainfun_end";
    case(definefuns_end):
        return "definefun_end";
    case(funreturns):
        return "funreturn";
    case(defineparas):
        return "definepara";
    case(ifstarts):
        return "ifstart";
    case(ifends):
        return "ifend";
    case(whilestarts):
        return "whilestart";
    case(whileends):
        return "whileend";
    case(forstarts):
        return "forstart";
    case(forends):
        return "forend";
    case(add_nexts):
        return "add_next";
    case(minus_nexts):
        return "minus_next";
    case(for_cmp):
        return "for_cmp";
    default:
        printf("匹配有误");
    }

}
//optimizetac.c  优化四元式
#include"global.h"
#include"optimize_TAC.h"

void start_optimize()
{
    optimer_tac();
    print_optimize_tac();
}
void optimer_tac()
{
    fourvarcode* t=tac_head->next;
    fourvarcode* p;
    fourvarcode* q;
    p=t->next;
    q=p->next;
    while(q!=NULL)
    {
        if(p->op==asns)
        {
            if(q->op==asns)
            {
                char a[20];
                strcpy(a,p->addr2.name);
                if(strcmp(p->addr2.name,q->addr1.name)==0&&a[0]=='t'&&a[1]=='#')
                {
                    strcpy(p->addr2.name,q->addr2.name);
                    p->next=q->next;
                    free(q);
                    q=p->next;
                }
                else
                {
                    t=t->next;
                    p=p->next;
                    q=q->next;
                }
            }

            else if(q->op!=asns) ///p可能需要删掉  比如return 0 的多于
            {
                char a[10],b[20],c[20];
                strcpy(a,p->addr1.name);
                strcpy(b,p->addr2.name);
                strcpy(c,q->addr3.name);
                if(strcmp(p->addr2.name,q->addr1.name)==0&&b[0]=='t'&&b[1]=='#'&&(c[0]=='\0'||a[1]=='#')&&q->op!=if_fs)
                {
                    strcpy(q->addr1.name,p->addr1.name);///将asn的值给下一句
                    t->next=p->next;
                    free(p);
                    p=t->next;
                    q=q->next;
                }
                else
                {
                    t=t->next;
                    p=p->next;
                    q=q->next;
                }
            }
        }
        else if(p->op!=asns)  ///如果不是赋值语句,那么它的下一句是赋值语句的话,且有运算
        {
            if(q->op==asns)
			{
				if(p->addr3.kind!=emptys)
				{
					char a[20];
				    strcpy(a,p->addr3.name);
					if(strcmp(p->addr3.name,q->addr1.name)==0&&a[0]=='t'&&a[1]=='#')
					{
						strcpy(p->addr3.name,q->addr2.name);///将赋值提前
						p->next=q->next;
						free(q);
						q=p->next;
					}
					else ///如果不是运算 --继续执行
					{
						t=t->next;
						p=p->next;
						q=q->next;
					}
				}
				else///如果不是运算 --继续遍历
				{
					t=t->next;
				    p=p->next;
					q=q->next;
				}
			}
			else  ///下一句也不是赋值语句,那么肯定继续搜索,没法简化
			{
				t=t->next;
				p=p->next;
				q=q->next;
			}
		}

    }
}
///输出简化后的四元式
void print_optimize_tac()
{
	fourvarcode* t=tac_head->next;
	while(t!=NULL)
	{
	    if(t->op==ifstarts||t->op==ifends||t->op==mainfuns_end||t->op==mainfuns||t->op==forstarts||t->op==forends||t->op==defineparas
            ||t->op==whilestarts ||t->op==whileends)
        {
            t=t->next;
        }
        else
        {
	    printf("(");
		printf("%s ,",opkinds_string(t->op));
		if(t->addr1.kind==emptys)
			printf("_ ,");
		else
			printf("%s ,",t->addr1.name);

		if(t->addr2.kind==emptys)
			printf("_ ,");
		else
			printf("%s ,",t->addr2.name);

		if(t->addr3.kind==emptys)
			printf("_ ,");
		else
			printf("%s ,",t->addr3.name);

		t=t->next;
		printf(")");
		printf("\n");
        }
	}
}

//symtable.c
#include"symtab.h"
#include"global.h"

static void insertNode(treenode * t);
static void nullProc(treenode * t);
void st_insert( char * name, int lineno, int loc );
int st_lookup ( char * name );
static void checkNode(treenode * t);
void printSymTab();
void buildSymtab(treenode * syntaxTree);
static void traverse(treenode * t,
                     void (* preProc) (treenode *),
                     void (* postProc) (treenode *) );


/* 基准选择16,2的4次方*/
#define SHIFT 4
#define SIZE 211
/* 返回哈希值,哈希函数 */
int location = 0;
static int hash(char* key)
{
    int t = 0;
    int i = 0;
    while(key[i] != '\0')
    {
        t = ((t<<SHIFT) + key[i]) % SIZE;
        i++;
    }
    return t;
}
typedef struct LineListRec
{
    int lineno;
    struct LineListRec * next;
} * LineList;

typedef struct BucketListRec
{
    char * name;
    LineList lines;
    int memloc ; /* memory location for variable */
    struct BucketListRec * next;
} * BucketList;

/* the hash table */
static BucketList hashTable[SIZE];

void start_symbtab()
{
    buildSymtab(tree_gen);
    //typeCheck(tree_gen);
}

void buildSymtab(treenode * syntaxTree)
{
    traverse(syntaxTree,insertNode,nullProc);
    if (1)
    {
        printf("\nSymbol table:\n\n");
        printSymTab();
    }
}


static void nullProc(treenode * t)
{
    if (t==NULL) return;
    else return;
}


/* Procedure insertNode inserts
 * identifiers stored in t into
 * the symbol table
 */
static void insertNode(treenode * t)
{
    switch (t->nodekind)
    {
    case stmtk:
        switch (t->kind.stmt)
        {
        case assignk:
        case defineparak:
            if (st_lookup(t->attr.name) == -1)
                /* not yet in table, so treat as new definition */
                st_insert(t->attr.name,t->lineno,location++);
            else
                /* already in table, so ignore location,
                   add line number of use only */
                st_insert(t->attr.name,t->lineno,0);
            break;
        default:
            break;
        }
        break;
    case expk:
        switch (t->kind.exp)
        {
        case idk:
            if (st_lookup(t->attr.name) == -1)
                /* not yet in table, so treat as new definition */
                st_insert(t->attr.name,t->lineno,location++);
            else
                /* already in table, so ignore location,
                   add line number of use only */
                st_insert(t->attr.name,t->lineno,0);
            break;
        default:
            break;
        }
        break;
    default:
        break;
    }
}

static void traverse(treenode * t,
                     void (* preProc) (treenode *),
                     void (* postProc) (treenode *) )
{
    if (t != NULL)
    {
        preProc(t);
        {
            int i;
            for (i=0; i < 4; i++)
                traverse(t->child[i],preProc,postProc);
        }
        postProc(t);
        traverse(t->sibling,preProc,postProc);
    }
}




void st_insert( char * name, int lineno, int loc )
{
    int h = hash(name);
    BucketList l =  hashTable[h];
    while ((l != NULL) && (strcmp(name,l->name) != 0))
        l = l->next;
    if (l == NULL) /* variable not yet in table */
    {
        l = (BucketList) malloc(sizeof(struct BucketListRec));
        l->name = name;
        l->lines = (LineList) malloc(sizeof(struct LineListRec));
        l->lines->lineno = lineno;
        l->memloc = loc;
        l->lines->next = NULL;
        l->next = hashTable[h];
        hashTable[h] = l;
    }
    else /* found in table, so just add line number */
    {
        LineList t = l->lines;
        while (t->next != NULL) t = t->next;
        t->next = (LineList) malloc(sizeof(struct LineListRec));
        t->next->lineno = lineno;
        t->next->next = NULL;
    }
} /* st_insert */

/* Function st_lookup returns the memory
 * location of a variable or -1 if not found
 */
int st_lookup ( char * name )
{
    int h = hash(name);
    BucketList l =  hashTable[h];
    while ((l != NULL) && (strcmp(name,l->name) != 0))
        l = l->next;
    if (l == NULL) return -1;
    else return l->memloc;
}

/* Procedure printSymTab prints a formatted
 * listing of the symbol table contents
 * to the listing file
 */
void printSymTab()
{
    int i;
    printf("Variable Name  Location   Line Numbers\n");
    printf("-------------  --------   ------------\n");
    for (i=0; i<SIZE; ++i)
    {
        if (hashTable[i] != NULL)
        {
            BucketList l = hashTable[i];
            while (l != NULL)
            {
                LineList t = l->lines;
                printf("%-14s ",l->name);
                printf("%-8d  ",l->memloc);
                while (t != NULL)
                {
                    printf("%4d ",t->lineno);
                    t=t->next;
                }
                printf("\n");
                l = l->next;
            }
        }
    }
} /* printSymTab */




/*void typeCheck(treenode * syntaxTree)
{
    traverse(syntaxTree,nullProc,checkNode);
}

static void typeError(treenode * t, char * message)
{
    fprintf(listing,"Type error at line %d: %s\n",t->lineno,message);

}*/
/*static void checkNode(treenode * t)
{ switch (t->nodekind)
  { case expk:
      switch (t->kind.exp)
      {
          case opk:
          if ((t->attr.op ==BIGGER ) || (t->attr.op == SMALLER)|| (t->attr.op == SMALLEREQU)||(t->attr.op ==BIGGEREQU)||(t->attr.op ==  NOTEQU)|| (t->attr.op ==IFEQU))
            t->type = Boolean;
          else
            t->type = Integer;
          break;
        case constk:
        case idk:
          t->type = Integer;
          break;
        default:
          break;
      }
      break;
    case stmtk:
      switch (t->kind.stmt)
      { case ifk:
          if (t->child[0]->type == Integer)
            typeError(t->child[0],"if test is not Boolean");
          break;
        case assignk:
          if (t->child[0]->type != Integer)
            typeError(t->child[0],"assignment of non-integer value");
          break;
        case WriteK:
          if (t->child[0]->type != Integer)
            typeError(t->child[0],"write of non-integer value");
          break;
        case RepeatK:
          if (t->child[1]->type == Integer)
            typeError(t->child[1],"repeat test is not Boolean");
          break;
        default:
          break;
      }
      break;
    default:
      break;

  }
}
*/





//asm.c
#include"global.h"
#include"asm.h"
#include"symtab.h"
void flocal_table(char type[],char name[],char num[],int n);
static void build_asm(fourvarcode* t);
static void find_function(fourvarcode* tac_head);
static void build_define(fourvarcode* t);
static void build_assign(fourvarcode* t);
static void build_label(fourvarcode* t);
static void build_jump(fourvarcode* t);
static void build_return(fourvarcode* t);
static void build_muls(fourvarcode* t); ///乘
static void build_divs(fourvarcode* t);  ///除
static void build_adds(fourvarcode* t);
static void build_minu(fourvarcode* t);
static void build_mainfuns(fourvarcode* t);
static void build_mainfuns_end(fourvarcode* t);
static void build_smas(fourvarcode* t);///<
static void build_smas_eqs(fourvarcode* t);///<=
static void build_big_equs(fourvarcode* t);
static void  build_bigs(fourvarcode* t);
static void build_eqs_eqs(fourvarcode* t);
static void build_not_eqs(fourvarcode* t);
void fglocal_table(char type[],char name[],char num[],int n);
symboltable *lsptempg,*lsptempl;///用于构造符号表的临时变量
fourvarcode* ltag;
char empty[]="\0";
int AX_FLAG=0,BX_FLAG=0,CX_FLAG=0,DX_FLAG=0,SI_FLAG=0;///通用寄存器
char assign_table[20][20];
int num=0;
symboltable *local_table;
int stackn=0;
char function_table[20][20]; ///函数名
int function_num = 0; ///函数个数

void flocal_table(char type[],char name[],char num[],int n)
{
    symboltable *t;
    t = (symboltable *)malloc(sizeof(symboltable));
    t->next = NULL;
    strcpy(t->type, type);
    strcpy(t->name, name);
    t->location=n;
    lsptempl->next=t;
    lsptempl=t;

}
void fglocal_table(char type[],char name[],char num[],int n)
{
    symboltable *t;
    t = (symboltable *)malloc(sizeof(symboltable));
    t->next = NULL;
    strcpy(t->type, type);
    strcpy(t->name, name);
    t->location=n;
    lsptempg->next=t;
    lsptempg=t;

}

int searchlocal(char a[20])
{
    symboltable *t=local_table->next;

    while(t!=NULL)
    {


        if(strcmp(t->name,a)==0)
        {
            return t->location;
            break;
        }
        t=t->next;
    }
    return -1;
}
void registerfree(char b[10])
{
    if(strcmp(b,"AX")==0||strcmp(b,"EAX")==0)
    {
        AX_FLAG=0;
    }
    if(strcmp(b,"BX")==0||strcmp(b,"EBX")==0)
    {
        BX_FLAG=0;
    }
    if(strcmp(b,"CX")==0||strcmp(b,"ECX")==0)
    {
        CX_FLAG=0;
    }

}
void start_asm()
{
    printf(".MODEL SMALL\n");
    printf(".386\n");
    printf(".STACK 100H\n");
    printf(".DATA\n");
    printf(".CODE\n");
    printf(".STARTUP\n");
    find_function(tac_head);
    local_table=(symboltable *)malloc(sizeof(symboltable));
    lsptempl=local_table;
    local_table->next=NULL;

    fourvarcode* t=tac_head->next;
    if(t->op!=mainfuns);
    {
        while(t->op!=mainfuns)
        {
            t=t->next;
        }
    }

    fourvarcode* q=t->next;

    ///***先解决函数定义的问题***///
    while(q->op!=mainfuns_end)
    {
        if(q->op==defineparas)
        {
            build_asm(q);
        }
        q=q->next;
    }

    build_asm(t); ///此时t是mainstart
    printf("push bp\n");
    printf("mov bp,sp\n");
    printf("jmp alloc\n");
    printf("main:\n");

    t=t->next; ///没有结束  建立其他的汇编

    while(t->op!=mainfuns_end)
    {
        if(t->op!=defineparas)
        {
            build_asm(t);
        }
        t=t->next;
    }
    build_asm(t);
    printf("jmp over\n");
    int i;
    printf("alloc:\n");
    for(i=num; i>=1; i--)
    {
        if(strcmp(assign_table[i],empty)==0)
        {
            printf("MOV AX,0\n");
            printf("PUSH AX\n");
        }
        else ///有赋值
        {
            printf("MOV AX,%s\n",assign_table[i]);
            printf("PUSH AX\n");
        }
    }
    printf("jmp main\n");
    printf("over:\n");
    printf(".exit\n");
    printf("end\n");

}

/***********************************************************
* 功能:将自定义函数存储起来
**********************************************************/
void find_function(fourvarcode* tac_head)
{
	fourvarcode *t = tac_head->next;
	while (t!=NULL)
	{
		if (t->op == definefuns)
		{
			strcpy(function_table[function_num++], t->addr1.name);
		}
		t = t->next;
	}

}

/***********************************************************
* 功能:全局定义的变量
**********************************************************/
void define_para(fourvarcode* tac_head)
{
	fourvarcode *t=tac_head->next;
	int num=0;
	//如果不为函数定义或主函数
	if(t->op!=definefuns&&t->op!=mainfuns)
	{
		while(t->op!=definefuns && t->op!=mainfuns)
		{
             flocal_table(t->addr1.name,t->addr2.name,t->addr3.name,num+1);
			t=t->next;
			num++;
		}
	}
	registerfree("AX");
	registerfree("BX");
	registerfree("CX");
}

/***********************************************************
* 功能:开始根据op来生成汇编代码
**********************************************************/
void build_asm(fourvarcode* t)
{
    if(t->op==defineparas)
    {
        build_define(t);
        return;
    }
    if(t->op==asns)
    {
        build_assign(t);
        return ;
    }
    if(t->op==labss)
    {
        build_label(t);
        return ;
    }
    if(t->op==jumps)
    {
        build_jump(t);
        return ;
    }
    if(t->op==returns)
    {
        build_return(t);
        return ;
    }
    if(t->op==minus)//-
    {
        build_minu(t);
        return ;
    }
    if(t->op==divs)//÷
    {
        build_divs(t);
        return ;
    }
    if(t->op==adds)//+
    {
        build_adds(t);
        return ;
    }
    if(t->op==muls)//*
    {
        build_muls(t);
        return ;
    }
    if(t->op==mainfuns)
    {
        build_mainfuns(t);
        return ;
    }
    if(t->op==mainfuns_end)
    {
        build_mainfuns_end(t);
        return ;
    }
    if(t->op==smas)
    {
        build_smas(t);
        return ;
    }
    if(t->op==sma_eqs)
    {
        build_smas_eqs(t);
        return ;
    }
    if(t->op==bigs)
    {
        build_bigs(t);
        return ;
    }
    if(t->op==big_eqs)
    {
        build_big_equs(t);
        return ;
    }
    if(t->op==if_eqs)
    {
        build_eqs_eqs(t);
        return;
    }
    if(t->op==not_eqs)
    {
        build_not_eqs(t);
        return ;
    }
    if(t->op==whilestarts) ///while
    {
        //build_whilestarts(t);
        return ;
    }
    if(t->op==whileends)
    {
        //build_whileends(t);
        return ;
    }
    if(t->op==forstarts)
    {
        return ;
    }
    if(t->op==forends)
    {
        return ;
    }
    /*if(t->op==begin_args)
    {
        build_funpara(t);
    }
    if(t->op==callfuns)
    {
        build_callfun(t);
    }
    */
}




/***********************************************************
* 功能:用于申请寄存器 为0则可以用
**********************************************************/
char *registerspare()
{
    if(AX_FLAG==0)
    {
        AX_FLAG=1;
        return "AX";
    }
    if(BX_FLAG==0)
    {
        BX_FLAG=1;
        return "BX";
    }

    if(CX_FLAG==0)
    {
        CX_FLAG=1;
        return "CX";
    }
    return "-1";
}



/***********************************************************
* 功能:
        具体建立汇编代码

**********************************************************/

void build_define(fourvarcode* t)  ///跟符号表有关了!!
{
    flocal_table(t->addr1.name,t->addr2.name,t->addr3.name,num+1);
    if(strcmp(t->addr3.name,empty)==0)这一定不是数组定义了
    {
        /* if(strcmp(t->addr1.content.name,"INT")==0)
         {
             ///if()如果是全局变量就要考虑 堆存储
             if()
             }*/
        num++;
    }
}


void build_assign(fourvarcode* t)
{
    char b[20],a1[20],a2[20];  ///a1 a2分别用来存储 赋值四元式的 值和变量名
    strcpy(a1,t->addr1.name);
    strcpy(a2,t->addr2.name);
    if(a1[0]>='0'&&a1[0]<='9')///数字赋给局部变量或者中间变量
    {
        if(((a2[0]>='a'&&a2[0]<='z')||(a2[0]>='A'&&a2[0]<='Z'))&&a2[1]!='#')///局部变量 形如这样的四元式= ,1,a,___
        {
            ///找一下当前变量是否在局部变量表
            if(searchlocal(t->addr2.name)!=(-1))
            {

                int n=searchlocal(t->addr2.name);
                if(strcmp(assign_table[n],empty)==0)
                {
                    strcpy(assign_table[n],t->addr1.name);
                    printf("MOV AX,%s\n",assign_table[n]);
                    printf("MOV [BP+%d],AX\n",n*2);

                }

                else  ///如果不是则为全局变量
                {
                    printf("MOV AX,%s\n",t->addr1.name);
                    printf("MOV [BP+%d],AX\n",n*2);
                }
            }
        }
        else  ///if(a2[1]=='#'形如 =,1,t#1
        {
            strcpy(b,registerspare());
            printf("MOV %s,%s\n",b,a1);
        }
    }

    else if(((a1[0]>='a'&&a1[0]<='z')||(a1[0]>='A'&&a1[0]<='Z'))&&a1[1]!='#')  ///形如这样的四元式 =,a,t#1,___ 主要翻译if while for (a<b)
    {
        ///中间变量寄存器的赋值

        int c1=searchlocal(a1);
        //if (a<b)中的a和b中间变量

        strcpy(b, registerspare());
        if (c1!=-1 )
        {
            printf("MOV %s,[BP+%d]\n", b, c1*2);
        }
        else
        {

            //printf("MOV %s,[BP+%d]\n", b, c1*2);
        }
    }
}
void build_label(fourvarcode* t)
{
    printf("%s:\n",t->addr1.name);
}

void build_jump(fourvarcode* t)
{
    printf("JMP %s\n",t->addr1.name);
}

void build_return(fourvarcode* t) ///为函数调用准备
{
    char a1[10];
    strcpy(a1,t->addr1.name);
    if(((a1[0]>='a'&&a1[0]<='z')||(a1[0]>='A'&&a1[0]<='Z'))&&a1[1]!='#')//返回局部变量
    {
        int d;
        //d=searchstack(a1);
        if(d>-1&&d<0)
        {
            d=-(d+2);
            printf("MOV BX,[BP+%d]\n",d);
            printf("MOV BP,SP\n");
        }
        else
        {
            printf("MOV [BP-2],AX \n");
        }

    }
    if(a1[1]=='#')//返回中间变量
    {

        if(AX_FLAG==1)
        {
            printf("MOV AX,BX\n");
            registerfree("AX");
        }
    }

}


void build_muls(fourvarcode* t) ///乘  x86中乘法的被乘数在AX里  结果在AX中
{
    char a3[10],axorbx[5];
    strcpy(a3,t->addr3.name);
    if(CX_FLAG==1)//用到cx寄存器了
    {

        printf("MUL BX,CX\n");
        strcpy(axorbx,"BX");
    }
    else
    {
        printf("MUL BX\n");
        AX_FLAG=1;
        strcpy(axorbx,"AX");
    }
    if(a3[1]!='#')//局部变量
    {
        int d;
        //d=searchstack(t->addr3.name);
        if(d>-1&&d<0)
        {
            d=-(d+2);
            printf("MOV [BP+%d],%s\n",d,axorbx);
            printf("MOV BP,SP\n");
        }
        else
        {
            if(stackn>=2)
                ;
            else
                printf("MOV [BP+%d],%s\n",d,axorbx);
        }

        if(strcmp(axorbx,"AX")==0)
        {
            registerfree("AX");
            registerfree("BX");
        }
        else
        {
            registerfree("BX");
            registerfree("CX");
        }
    }
    else//结果仍然留在AX 中
    {
        if(strcmp(axorbx,"AX")==0)
        {
            registerfree("BX");
        }
        else
        {
            registerfree("CX");
        }
    }
}

void build_divs(fourvarcode* t)  ///除
{
    char a3[10],axorbx[5];
    strcpy(a3,t->addr3.name);
    if(CX_FLAG==1)//用到cx寄存器了
    {
        printf("DIV BX,CX\n");
        strcpy(axorbx,"BX");
    }
    else
    {
        printf("DIV BX\n");
        strcpy(axorbx,"AX");
    }
    if(a3[1]!='#')
    {
        int d=searchlocal(t->addr3.name);
        if(d==-1)
        {
            printf("MOV [BP+%d],%s\n",d,axorbx);
            printf("MOV BP,SP\n");
        }
        //当数在局部变量符号表里
        else
        {

            printf("MOV [BP+%d],%s\n",d*2,axorbx);
        }

        if(strcmp(axorbx,"AX")==0)
        {
            registerfree("AX");
            registerfree("BX");
        }
        else
        {
            registerfree("BX");
            registerfree("CX");
        }
    }
    //结果仍然留在AX 中
    else
    {
        if(strcmp(axorbx,"AX")==0)registerfree("BX");
        else registerfree("CX");
    }
}



void build_adds(fourvarcode* t)
{
    char a2[10],a3[10],axorbx[5];
    strcpy(a2,t->addr2.name);
    strcpy(a3,t->addr3.name);
    if(strcmp(a2,"1")!=0)//不是自增运算
    {
        if(CX_FLAG==1)//用到cx寄存器了
        {
            printf("ADD BX,CX\n");
            strcpy(axorbx,"BX");
        }
        else
        {
            printf("ADD AX,BX\n");
            strcpy(axorbx,"AX");
        }
        if(a3[1]!='#')///结果赋值给局部变量
        {
            int d=searchlocal(t->addr3.name);
            if(d==-1)
            {;
                printf("MOV [BP+%d],%s\n",d,axorbx);
                printf("MOV BP,SP\n");
            }
            ///当数在局部变量符号表里
            else
            {

                printf("MOV [BP+%d],%s\n",d*2,axorbx);
            }
            if(strcmp(axorbx,"AX")==0)
            {
                registerfree("AX");
                registerfree("BX");
            }
            else
            {
                registerfree("BX");
                registerfree("CX");
            }
        }
        ///结果仍然留在AX 中
        else
        {
            if(strcmp(axorbx,"AX")==0)
            {
                registerfree("BX");
            }
            else
            {
                registerfree("CX");
            }
        }
    }
}



void build_minu(fourvarcode* t)
{
    char a2[10],a3[10],axorbx[5];
    strcpy(a2,t->addr2.name);
    strcpy(a3,t->addr3.name);
    if(strcmp(a2,"1")!=0)
    {
        if(CX_FLAG==1)///用到cx寄存器了
        {
            printf("SUB BX,CX\n");
            strcpy(axorbx,"BX");
        }
        else
        {
            printf("SUB AX,BX\n");
            strcpy(axorbx,"AX");
        }
        if(a3[1]!='#')
        {
            int d;
            //d=searchstack(t->addr3.name);
            if(d>-1&&d<0)
            {
                d=-(d+2);
                printf("MOV [BP+%d],%s\n",d,axorbx);
                printf("MOV BP,SP\n");
            }
            else
            {
                printf("MOV [BP+%d],%s\n",d,axorbx);
            }
            if(strcmp(axorbx,"AX")==0)
            {
                registerfree("AX");
                registerfree("BX");
            }
            else
            {
                registerfree("BX");
                registerfree("CX");
            }
        }
        else
        {
            if(strcmp(axorbx,"AX")==0)registerfree("BX");
            else registerfree("CX");
        }
    }

}

void build_mainfuns(fourvarcode* t)
{
    return;
}

void build_mainfuns_end(fourvarcode* t)
{
    return;
}
void build_smas(fourvarcode* t)///<
{
    printf("CMP AX,BX\n");
    printf("JAE %s\n",t->next->addr2.name);///a>=b 则跳走 --所以这里用来处理小于  也能用JNB
    registerfree("BX");
}

void build_smas_eqs(fourvarcode* t)///<=
{
    printf("CMP AX,BX\n");
    printf("JA %s\n",t->next->addr2.name);///a<b则跳走  否则继续执行
    registerfree("BX");
}

void  build_bigs(fourvarcode* t)
{
    printf("CMP AX,BX\n");
    printf("JBE %s\n",t->next->addr2.name); ///A<=B则跳走
}

void build_big_equs(fourvarcode* t)
{
    printf("CMP AX,BX\n");
    printf("JB %s\n",t->next->addr2.name); ///A<B则跳走
}
void build_eqs_eqs(fourvarcode* t)
{
    printf("CMP AX,BX\n");
    printf("JNE %s\n",t->next->addr2.name);///A!=B则跳走
}

void build_not_eqs(fourvarcode* t)
{
    printf("CMP AX,BX\n");
    printf("JE %s\n",t->next->addr2.name); ///相等就跳走
}
void build_funpara(fourvarcode* t)
{
    fourvarcode* t1;
    int c,i,cnt;
    sscanf(t->addr1.name,"%d",&c);

    //如果C=0则没有传递参数
    if(c==0)
        return;
    t1=t->next;
    for(i=c,cnt=c; i>0; cnt--)
    {
        if(i!=1)
        {
            while(i!=1)
            {
                if(t1->op==args)i--;
                t1=t1->next;
            }
        }
        else i--;
        if(t1->op!=args)
        {
            while(t1->op!=args)
            {
                build_asm(t1);
                t1=t1->next;
            }
        }
        if(cnt==c)ltag=t1;
        //t1->op=args

        //找参数地址
        char a[20];
        strcpy(a,t1->addr1.name);
        char b[20];
        //strcpy(b,registerspare());
        if (CX_FLAG == 1)
            strcpy(b,"CX");
        else if(BX_FLAG==1)
            strcpy(b,"BX");
        else//AX_FLAG=1
            strcpy(b,"AX");
        if(((a[0]>='a'&&a[0]<='z')||(a[0]>='A'&&a[0]<='Z'))&&a[1]!='#')//局部变量
        {
            int d;
            //d=searchstack(a);
            //如果找到了参数已经被定义
            if(d==-1)
            {

                printf("MOV %s,[BP+%d]\n",b,d*2);
                printf("MOV BP,SP\n");
            }
            else
                printf("MOV %s,[BP+%d]\n",b,d*2);
        }
        if(a[0]>='0'&&a[0]<='9')
        {
            printf("MOV %s,%s\n",b,a);
        }
        printf("PUSH %s\n",b);//传递中间变量
        registerfree(b);
        t1=t->next;//为传入的局部变量
    }

}
void build_callfun(fourvarcode *t)
{
    printf("call near ptr %s\n",t->addr1.name);

}

参考资料:

《编译原理及实践》

虎书

[鲸书][高级编译器设计与实现](Steven.S.Muchnic

用C语言实现一个C语言的编译器的相关内容如下:

[$]dbdbdbdbdbdbdb[/$]
支付0.01元,限次查看(10次)

本文标题:用C语言实现一个C语言的编译器
http://www.tainingxinwen.cn/qitaxinxi/616112.html

0

精彩评论

暂无评论...
验证码 换一张
取 消