C#开发一个小型编译器

来源:互联网 发布:c语言简易病毒 编辑:程序博客网 时间:2024/04/29 01:20
设计任务为开发一个小型编译器,主要包括4个部件:词法分析器、语法分析器、语义分析器、目标代码生成器。

一、课程设计的目的与要求
1.通过设计、编写和调试词法分析程序,了解词法扫描器的组成结构、不同种类单词的识别方法,掌握由单词的词法规则出发,通过识别单词的状态转换图、利用程序实现词法扫描器的方法。
1.1扫描器设计
该扫描器是一个子程序,其输入是源程序字符串,每调用一次输出一个单词符号。为了避免超前搜索,提高运行效率,简化扫描器的设计,假设程序设计语言中,基本字不能用作一般标识符,如果基本字、标识符和常数之间没有确定的运算符或界符作间隔,则用空白作间隔。
2.通过设计、编写和调试语法分析程序,了解语法分析器的组成结构以及对文法的要求,掌握基于LL(1)文法或算符优先文法的语法分析程序的实现方法。
2.1语法分析器设计
以算法优先分析方法为例,设计一个算符优先语法分析程序。算符优先分析属于自下而上的分析方法,该语法分析程序的输入是终结符号串(即单词符号串,以一个“#”结尾),如果输入串是句子则输出“YES”,否则输出“NO”和错误信息。当然,也可采用预测分析等方法设计语法分析器,具体方法自定。
3.通过设计、编写和调试语法制导翻译程序,掌握从语句的语法出发,构造相应的语义子程序,实现自定义语言的语法制导翻译。
3.1语法制导翻译程序设计
采用语法制导翻译方法,实现算术表达式、赋值语句和基本控制语句等的翻译。本语法制导翻译程序的输入是终结符号串(即单词符号串,以一个“#”结尾),如果输入符号串是句子,则按照其语义进行翻译,输出等价的四元式序列。
4.目标代码生成器设计,将程序设计语言的中间代码程序翻译为目标代码程序,其输入是四元式序列,输出是一个汇编代码文件。
二、设计(实验)正文
1. 词法分析器设计
1.1 单词符号表



1.2 可实现的功能
1) 输入:字符串(待进行词法分析的源程序);
输出:一个单词序列文件(即:token文件)和一个符号表文件,并输出错误信息。
显示为(种别码,自身值)格式的二元式。
2) 功能:
a. 过滤空格、回车、换行符等无用字符
b. 识别保留字并转换成种别码
c. 识别标识符
d. 识别界符
3) 检查如下错误:
a. 程序语言的字符集以外的非法字符
b. 单词拼错,如可识别标识符开头为数字的拼写错误
1.3 基本流程
首先判断输入的字符是否为0-9或a-z或A-Z,再判断输入的字符串中是否含关键字,若不是关键字则判断是否为整型常数。当出现* / + - = ; ( ) #停止并直接输出,当出现< > :时需判断该符号后是否有其他符号组成<> 、<= 、>=、 := ,若组成这些符号则停止并输出这些符号的种别码,否则直接输出< > :的种别码。当回车时换行,若遇到无法识别的字符则输出错误信息。
2. 递归下降分析程序设计
2.1 设置递归下降文法
程序定义:
〈程序〉→ program〈标识符〉〈程序体〉.
〈程序体〉→〈变量说明〉〈复合句〉
变量定义:
〈变量说明〉→ var〈变量定义〉|ε
〈变量定义〉→〈标识符表〉:〈类型〉;|〈标识符表〉:〈类型〉;〈变量定义〉
〈标识符表〉→〈标识符〉,〈标识符表〉|〈标识符〉
语句定义:
〈复合句〉→ begin〈语句表〉end
〈语句表〉→〈执行句〉;〈语句表〉|〈执行句〉
〈执行句〉→〈简单句〉|〈结构句〉
〈简单句〉→〈赋值句〉
〈赋值句〉→〈变量〉:=〈表达式〉
〈变量〉→〈标识符〉
〈结构句〉→〈复合句〉|〈if句〉|〈WHILE句〉
〈if句〉→ if〈布尔表达式〉then〈执行句〉| if〈布尔表达式〉then〈执行句〉else〈执行句〉
〈while句〉→ while〈布尔表达式〉do〈执行句〉
表达式定义:
〈表达式〉→〈算术表达式〉|〈布尔表达式〉
〈算术表达式〉→〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉|〈项〉
〈项〉→〈项〉*〈因子〉|〈项〉/〈因子〉|〈因子〉
〈因子〉→〈算术量〉|(〈算术表达式〉)
〈算术量〉→〈标识符〉|〈整数〉|〈实数〉
〈布尔表达式〉→〈布尔表达式〉or〈布尔项〉|〈布尔项〉
〈布尔项〉→〈布尔项〉and〈布尔因子〉|〈布尔因子〉
〈布尔因子〉→ not〈布尔因子〉|〈布尔量〉
〈布尔量〉→〈布尔常数〉|〈标识符〉|(〈布尔表达式〉)|〈关系表达式〉
〈关系表达式〉→〈标识符〉〈关系运算符〉〈标识符〉
〈关系运算符〉→〈|〈= | =| 〉=| 〉|〈〉
类型定义:
〈类型名〉→ integer|bool | real
单词定义:
〈标识符〉→〈字母〉|〈标识符〉〈字母〉|〈标识符〉〈数字〉
〈整数〉→〈数字〉|〈整数〉〈数字〉
〈实数〉→〈整数〉.|〈实数〉〈数字〉
〈布尔常数〉→ true|false
字符定义:
〈字母〉→ A│B│C│D│E│F│G│H│I│J│K│L│M│N│O│P│Q│R│S│T│
U│V│W│X│Y│Z│a│b│c│d│e│f│g│h│i│j│k│l│m│n│o│
p│q│r│s│t│u│v│w│x│y│z
〈数字〉→ 0│1│2│3│4│5│6│7│8│9
2.2 可实现的功能
程序输入窗口输入字符串,然后进行递归下降分析,分析过程中如有错误,则终止程序并报告错误原因。若输入串合法则显示正确,若不合法则显示错误信息。
2.3 基本流程
输入一段程序,首先检索第一个单词是否为program,如果是则检索下一个单词是否是标识符,否则输出错误信息:该程序缺少关键字:program;如果下一个单词是标识符,则进行程序体的检索,否则输出错误信息:该程序program缺少方法名;如此依照递归下降的方法,逐步自上而下的判断语法是否符合制定的语义规则。当所有检索结束,无错误时即输出“正确”。
2.4 实验难点
算符优先分析方法只能分析类似于算数表达式这样结构的语句,但本实验采用递归下降方法,包括了整个程序的分析过程,这其中较困难的是解决算数表达式和逻辑表达式的结合性问题,解决方案是将表达式细分为因子、项等逻辑单位来确定优先性。
3. 语法制导翻译程序设计
3.1 设计流程


3.2 可实现的功能
输入:token文件、符号表文件,其数据结构与词法分析产生的文件相同。
输出:四元式序列文件,其纪录结构:(操作,做操作数,右操作数,结果)
3.3 实验内容
该程序的设计是在语法分析的程序的基础之上添加了输出四元式的功能。
4. 目标代码生成
4.1 设计流程





4.2 数据结构
输入:四元式序列文件和符号表文件,其结构与语法/语义分析程序的输出一致。
输出:一个汇编代码文件,并无特殊数据结构。

三、课程设计(综合实验)总结或结论
本次实验达到了实验目的,成功的实现了词法分析器、语法语义分析器的功能,能够对一段简单的L语言程序代码进行词法、语法、语义分析,能够正确的输出单词的种别码,能够判断代码是否符合语法规则,若不符合能报出相应错误信息,能对代码进行语义的翻译,显示出等价的四元式。
通过这次实验,我的学习能力得到了很好的锻炼。三个实验的内容都是课堂上学习的,但理论知识和实践不能划等号,能够做出作业题并不代表能做出一个初具功能的编译器,需要熟练的掌握编译知识。
通过这次实验,我还有了意外的收获,初步学习了一门新的高级程序设计语言C#,熟悉了在.NET环境下的编程,实现了WEB版编译器。C#作为典型的面向对象的语言,在语法上和C++确实有很大不同,但整个功能实现的思路是差不多的。
以下是各部分实验中的心得和遇到的问题:
1.词法分析器设计
此次实验加深了对课堂教学内容的理解,培养了解决实际问题能力。通过这个实验,使我能应用编译程序设计的原理和技术设计出词法分析器,了解扫描器的组成结构,不同种类单词的识别方法,学会判断一个字符串是数字、字母、关键字,学会了超前搜索。
2.递归下降程序设计
此次实验加深了对课堂教学内容的理解,培养了解决实际问题能力。通过这个实验,使我能应用编译程序设计的原理和技术, 设计、编写和调试递归下降分析程序,了解递归下降分析程序的组成结构,掌握实现通用递归下降分析算法的方法,能够分析出一段程序代码是否符合规定语法,如果不符合能够显示错误原因。
3.基于递归下降分析的语法制导翻译设计
此次实验加深对了课堂教学内容的理解,培养了解决实际问题能力。通过这个实验,使我能应用编译程序设计的原理和技术, 通过设计、编写和调试语法制导翻译程序,掌握从一种语句的语法和语义出发,构造相应的语义子程序,实现基于算符优先分析方法的语法制导翻译的方法,能够正确的输出等价的四元式。

运行结果:





具体的实现过程:


主要的几个类:

Morophology.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace 编译{    public class Morphology    {        string[] machineCodes = new string[38];        public List<token> tokens = new List<token>();        public List<symble> symbles = new List<symble>();        public List<Error> errors = new List<Error>();        string input;        int i = 0;        int rowNum = 1;        public Morphology(string s)//传入字符串        {            input = s + " ";            NewKeyWord();//定义机内码            Dispose();//主程序        }        #region 定义机内码        private void NewKeyWord()        {            machineCodes[0] = "";            machineCodes[1] = "and";            machineCodes[2] = "begin";            machineCodes[3] = "bool";            machineCodes[4] = "do";            machineCodes[5] = "else";            machineCodes[6] = "end";            machineCodes[7] = "false";            machineCodes[8] = "if";            machineCodes[9] = "integer";            machineCodes[10] = "not";            machineCodes[11] = "or";            machineCodes[12] = "program";            machineCodes[13] = "real";            machineCodes[14] = "then";            machineCodes[15] = "true";            machineCodes[16] = "var";            machineCodes[17] = "while";            machineCodes[18] = "标志符";            machineCodes[19] = "整数";            machineCodes[20] = "实数";            machineCodes[21] = "(";            machineCodes[22] = ")";            machineCodes[23] = "+";            machineCodes[24] = "-";            machineCodes[25] = "*";            machineCodes[26] = "/";            machineCodes[27] = ".";            machineCodes[28] = ",";            machineCodes[29] = ":";            machineCodes[30] = ";";            machineCodes[31] = ":=";            machineCodes[32] = "=";            machineCodes[33] = "<=";            machineCodes[34] = "<";            machineCodes[35] = "<>";            machineCodes[36] = ">";            machineCodes[37] = ">=";        }        #endregion        #region 处理输入的代码        public void Dispose()        {            while (i < input.Length)//只要不超出字符串长度就继续执行            {                if (IsAlpha(input[i]))                {                    RecogId();                }                else if (IsDight(input[i]))                {                    RecogCons();                }                else if (input[i] == '/')                {                    i++;                    if (input[i] == '/')                    {                        while (input[i] != '\r' && i < input.Length)                        {                            i++;                        }                    }                    else                    {                        i--;                    }                }                else if (input[i] == '\r' && input[i + 1] == '\n')                {                    rowNum++;                    i++;                    i++;                }                else if (IsDelimiter(input[i]))                {                    RecogSym();                }                else if (input[i] == ' ')                {                    i++;                }                else                {                    Error e = new Error(rowNum, input[i].ToString(), "(1)非法字符");                    errors.Add(e);                    i++;                }            }        }         #endregion        #region 判断是标识符还是关键字并处理        private void RecogId()        {            string str = "";            int code;            do            {                str = str + input[i];                i++;            } while (IsAlpha(input[i]) || IsDight(input[i]));//判断是不是字母或数字,是的话继续执行            code = Reserve(str);            token t = new token();//存入token文件            t.Label = tokens.Count;            t.Name = str;            if (code == 0)            {                t.Code = 18;                t.Addr = symbles.Count;                symble s = new symble();//存入符号表                s.Number = t.Addr;                s.Name = str;                s.Type = 18;                symbles.Add(s);            }            else            {                t.Code = code;                t.Addr = -1;            }            tokens.Add(t);        }        #endregion        #region 判断是不是常数并处理        private void RecogCons()        {            string str = input[i].ToString();            bool flag = true;            bool point = true;            while (flag)            {                i++;                if (IsDight(input[i]))                {                    str += input[i];                }                else if (input[i] == '.')                {                    if (point)                    {                        str += input[i];                        point = false;                    }                    else                    {                        Error e = new Error(rowNum, str, "出现第二个'.'号");                        errors.Add(e);                        flag = false;                    }                }                else if (IsAlpha(input[i]))                {                    i++;                    if (IsDight(input[i]))                    {                        i--;                        i--;                        if (point)                        {                            Error e = new Error(rowNum, str, "数字开头的数字、字母串");                            errors.Add(e);                        }                        else                        {                            Error e = new Error(rowNum, str, "实数的小数部分出现字母");                            errors.Add(e);                        }                    }                }                else                 {                    flag = false;                }            }            if (point)            {                token t = new token();                t.Label = tokens.Count;                t.Name = str;                t.Code = 19;                t.Addr = symbles.Count;                symble s = new symble();                s.Number = t.Addr;                s.Name = str;                s.Type = 19;                symbles.Add(s);                tokens.Add(t);            }            else            {                token t = new token();                t.Label = tokens.Count;                t.Name = str;                t.Code = 20;                t.Addr = symbles.Count;                symble s = new symble();                s.Number = t.Addr;                s.Name = str;                s.Type = 20;                symbles.Add(s);                tokens.Add(t);            }        }        #endregion        #region 判断是否是符号并处理        private void RecogSym()        {            string str = "" + input[i];            if (str == ":" || str == "<" || str == ">")            {                i++;                if (input[i] == '=')                {                    str += input[i];                }                else if (input[i] == '>' && str == "<")                {                    str += input[i];                }                else                {                    i--;                }            }            for (int j = 21; j <= 37; j++)            {                if (str == machineCodes[j])                {                    token t = new token();                    t.Label = tokens.Count;                    t.Name = str;                    t.Code = j;                    t.Addr = -1;                    tokens.Add(t);                    i++;                }            }        }        #endregion        #region 判断是不是字母        private bool IsAlpha(char c)        {            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))            {                return true;            }            else            {                return false;            }        }        #endregion        #region 判断是不是数字        private bool IsDight(char c)        {            if (c >= '0' && c <= '9')            {                return true;            }            else            {                return false;            }        }        #endregion        #region 判断是不是其他界符        private bool IsDelimiter(char c)        {                    switch (c)            {                case '(':  return true;                case ')':  return true;                case '+':  return true;                case '-':  return true;                case '*':  return true;                case '.':  return true;                case ',':  return true;                case ':':  return true;                case ';':  return true;                case '=':  return true;                case '<':  return true;                case '>':  return true;                default: return false;            }        }        #endregion        #region 匹配机内码        private int Reserve(string str)        {            for (int i = 1; i <= 17; i++)            {                                if (str == machineCodes[i])                {                    return i;//返回机内码编号                }            }            return 0;//标识符        }         #endregion    }}
Grammar.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 编译{    public class Grammar    {        List<token> tokens;        List<symble> symbles;        public string error = "";        int i = 0;        public Grammar(Morphology m)        {            tokens = m.tokens;            symbles = m.symbles;            Dispose();        }        private void Next()        {            if (i < tokens.Count - 1)            {                i++;            }        }        private void Before()        {            if (i > 0)            {                i--;            }        }        #region 主要函数        private void Dispose()        {            if (tokens[i].Code == 12)//含有program            {                Next();                if (tokens[i].Code == 18)//是标识符                {                    //执行程序体                    Next();                    ProBody();                }                else                {                    error = "该程序program缺少方法名";                }            }            else            {                error = "该程序缺少关键字:program";            }        }        #endregion        #region 程序体        private void ProBody()        {            if (tokens[i].Code == 16)//判断var            {                Next();                VarDef();            }            else if (tokens[i].Code == 2)//判断begin            {                Next();                ComSent();            }            else            {                error = "程序体缺少var或begin";            }        }        #endregion        #region 变量定义        private void VarDef()        {            if (IsIdlist())            {                Next();                if (tokens[i].Code == 29)//:                {                    Next();                    if (tokens[i].Code == 9 || tokens[i].Code == 3 || tokens[i].Code == 13)//integer,bool,real                    {                        int j = i;                        j = j - 2;                        symbles[tokens[j].Addr].Type = tokens[i].Code;                        j--;                        while (tokens[j].Code == 28)                        {                            j--;                            symbles[tokens[j].Addr].Type = tokens[i].Code;                        }                        Next();                        if (tokens[i].Code == 30)                        {                            Next();                            if (tokens[i].Code == 2)                            {                                Next();                                ComSent();                            }                            else                            {                                VarDef();                            }                        }                        else                        {                            error = "变量定义后面缺少;";                        }                    }                    else                    {                        error = "变量定义缺少类型或类型定义错误";                        return;                    }                }                else                {                    error = "var后面缺少冒号";                }            }            else            {                error = "变量定义标识符出错";            }        }        #endregion        #region 判断是不是标识符表        private bool IsIdlist()        {            if (tokens[i].Code == 18)            {                Next();                if (tokens[i].Code == 28)//,                {                    Next();                    return IsIdlist();                }                else                {                    Before();                    return true;                }            }            else            {                return false;            }        }        #endregion        #region 复合句        private void ComSent()        {            SentList();            if (error == "")            {                if (tokens[i].Code == 6)                {                    return;                }                else                {                    error = "复合句末尾缺少end";                }            }        }        #endregion        #region 语句表        private void SentList()        {            ExecSent();            if (error == "")            {                Next();                if (tokens[i].Code == 30)                {                    Next();                    SentList();                }            }        }        #endregion        #region 执行句        private void ExecSent()        {            if (tokens[i].Code == 18)            {                Next();                AssiSent();            }            else if (tokens[i].Code == 2 || tokens[i].Code == 8 || tokens[i].Code == 17)            {                StructSent();            }            else            {                Before();            }        }        #endregion        #region 赋值句        private void AssiSent()        {            if (tokens[i].Code == 31)//:=            {                Next();                Expression();            }            else            {                error = "赋值句变量后缺少:=";            }        }        #endregion        #region 表达式        private void Expression()        {            if (tokens[i].Code == 7 || tokens[i].Code == 15 || (tokens[i].Addr != -1 && symbles[tokens[i].Addr].Type == 3))            {                BoolExp();            }            else            {                AritExp();            }        }        #endregion        #region 布尔表达式        private void BoolExp()        {            BoolItem();            if (error == "")            {                Next();                if (tokens[i].Code == 11)                {                    Next();                    BoolExp();                }                else                {                    Before();                }            }            else            {                return;            }        }        #endregion        #region 布尔项        private void BoolItem()        {            BoolFactor();            if (error == "")            {                Next();                if (tokens[i].Code == 1)                {                    Next();                    BoolItem();                }                else                {                    Before();                }            }        }        #endregion        #region 布尔因子        private void BoolFactor()        {            if (tokens[i].Code == 10)            {                Next();                BoolFactor();            }            else            {                BoolValue();            }        }        #endregion        #region 布尔量        private void BoolValue()        {            if (tokens[i].Code == 15 || tokens[i].Code == 7)            {                return;            }            else if (tokens[i].Code == 18)            {                Next();                if (tokens[i].Code == 34 || tokens[i].Code == 33 || tokens[i].Code == 32 || tokens[i].Code == 37 || tokens[i].Code == 36 || tokens[i].Code == 35)                {                    Next();                    if (tokens[i].Code == 18)                    {                    }                    else                    {                        error = "关系运算符后缺少标识符";                    }                }                else                {                    Before();                }            }            else if (tokens[i].Code == 21)            {                BoolExp();                //?                if (tokens[i].Code == 22)                {                    return;                }                else                {                    error = "布尔量中的布尔表达式缺少一个)";                }            }            else            {                error = "布尔量出错";            }        }        #endregion        #region 算数表达式        private void AritExp()        {            Item();            if (error == "")            {                Next();                if (tokens[i].Code == 23 || tokens[i].Code == 24)                {                    Next();                    AritExp();                }                else                {                    Before();                    return;                }            }            else            {                return;            }        }        #endregion        #region 项        private void Item()        {            Factor();            if (error == "")            {                Next();                if (tokens[i].Code == 25 || tokens[i].Code == 26)                {                    Next();                    Item();                }                else                {                    Before();                    return;                }            }            else            {                return;            }        }        #endregion        #region 因子        private void Factor()        {            if (tokens[i].Code == 21)            {                Next();                AritExp();                Next();                if (tokens[i].Code == 22)                {                    return;                }                else                {                    error = "因子中算数表达式缺少)";                }            }            else            {                CalQua();            }        }        #endregion        #region 算数量        private void CalQua()        {            if (tokens[i].Code == 18 || tokens[i].Code == 19 || tokens[i].Code == 20)            {                return;            }            else            {                error = "算数量出错";            }        }        #endregion        #region 结构句        private void StructSent()        {            if (tokens[i].Code == 2)            {                Next();                ComSent();            }            else if (tokens[i].Code == 8)            {                Next();                IfSent();            }            else if (tokens[i].Code == 17)            {                Next();                WhileSent();            }        }        #endregion        #region if语句        private void IfSent()        {            BoolExp();            if (error == "")            {                Next();                if (tokens[i].Code == 14)                {                    Next();                    ExecSent();                    Next();                    if (tokens[i].Code == 5)                    {                        Next();                        ExecSent();                    }                    else                    {                        Before();                        return;                    }                }                else                {                    error = "if...then语句缺少then";                }            }            else            {                error = "if语句布尔表达式出错";            }        }        #endregion        #region while语句        private void WhileSent()        {            BoolExp();            if (error == "")            {                Next();                if (tokens[i].Code == 4)                {                    Next();                    ExecSent();                }                else                {                    error = "while语句缺少do";                }            }        }        #endregion    }}
semantic.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 编译{    public class Semantic    {        public List<FourPart> fps = new List<FourPart>();        public List<E> es = new List<E>();        List<token> tokens;        public List<symble> symbles=new List<symble>();        public string error = "";        int i = 0;        int ti = 1;        string tt = "";        public Semantic(Morphology m)        {            tokens = m.tokens;            symbles = m.symbles;            Dispose();        }        private void Next()        {            if (i < tokens.Count - 1)            {                i++;            }        }        private void Before()        {            if (i > 0)            {                i--;            }        }        #region 创建临时变量        private string NewTemp()        {            string temp = "T" + ti.ToString();            ti++;            symble s=new symble();            s.Name=temp;            symbles.Add(s);            return temp;        }        #endregion        #region 回填函数        private void BackPatch(int addr, int addr2)        {            fps[addr].JumpNum = addr2.ToString();        }        #endregion        #region 产生四元式        private void Emit(string op, string strLeft, string strRight, string jumpNum)        {            FourPart fp = new FourPart(op, strLeft, strRight, jumpNum);            fps.Add(fp);        }        #endregion        #region 主要函数        private void Dispose()        {            if (tokens[i].Code == 12)//含有program            {                Next();                if (tokens[i].Code == 18)//是标识符                {                    Emit("program", tokens[i].Name, "_", "_");                    //执行程序体                    Next();                    ProBody();                }                else                {                    error = "该程序program缺少方法名";                }            }            else            {                error = "该程序缺少关键字:program";            }        }        #endregion        #region 程序体        private void ProBody()        {            if (tokens[i].Code == 16)            {                Next();                VarDef();            }            else if (tokens[i].Code == 2)            {                Next();                ComSent();            }            else            {                error = "程序体缺少var或begin";            }        }        #endregion        #region 变量定义        private void VarDef()        {            if (IsIdlist())            {                Next();                if (tokens[i].Code == 29)//:                {                    Next();                    if (tokens[i].Code == 9 || tokens[i].Code == 3 || tokens[i].Code == 13)//integer,bool,real                    {                        int j = i;                        j = j - 2;                        symbles[tokens[j].Addr].Type = tokens[i].Code;                        j--;                        while (tokens[j].Code == 28)                        {                            j--;                            symbles[tokens[j].Addr].Type = tokens[i].Code;                        }                        Next();                        if (tokens[i].Code == 30)                        {                            Next();                            if (tokens[i].Code == 2)                            {                                Next();                                ComSent();                            }                            else                            {                                VarDef();                            }                        }                        else                        {                            error = "变量定义后面缺少;";                        }                    }                    else                    {                        error = "变量定义缺少类型或类型定义错误";                        return;                    }                }                else                {                    error = "var后面缺少冒号";                }            }            else            {                error = "变量定义标识符出错";            }        }        #endregion        #region 判断是不是标识符表        private bool IsIdlist()        {            if (tokens[i].Code == 18)            {                Next();                if (tokens[i].Code == 28)//,                {                    Next();                    return IsIdlist();                }                else                {                    Before();                    return true;                }            }            else            {                return false;            }        }        #endregion        #region 复合句        private void ComSent()        {            SentList();            if (error == "")            {                if (tokens[i].Code == 6)                {                    Emit("sys", "_", "_", "_");                }                else                {                    error = "复合句末尾缺少end";                }            }        }        #endregion        #region 语句表        private void SentList()        {            S s = new S();            ExecSent(ref s);            if (error == "")            {                Next();                if (tokens[i].Code == 30)                {                    Next();                    SentList();                }            }        }        #endregion        #region 执行句        private void ExecSent(ref S s)        {            if (tokens[i].Code == 18)            {                Next();                AssiSent();            }            else if (tokens[i].Code == 2 || tokens[i].Code == 8 || tokens[i].Code == 17)            {                StructSent(ref s);            }            else            {                Before();            }        }        #endregion        #region 赋值句        private void AssiSent()        {            if (tokens[i].Code == 31)//:=            {                string temp = tokens[i - 1].Name;                Next();                Expression();                Emit(":=", tt, "_", temp);            }            else            {                error = "赋值句变量后缺少:=";            }        }        #endregion        #region 表达式        private void Expression()        {            if (tokens[i].Code == 7 || tokens[i].Code == 15 || (tokens[i].Addr != -1 && symbles[tokens[i].Addr].Type == 3))            {                E e = new E();                BoolExp(ref e);            }            else            {                AritExp();            }        }        #endregion        #region 布尔表达式        private void BoolExp(ref E e)        {            E e1 = new E();            BoolItem(ref e1);            if (error == "")            {                Next();                if (tokens[i].Code == 11)                {                    int m = fps.Count;                    E e2 = new E();                    Next();                    BoolExp(ref e2);                    e.t.Concat(e1.t);                    e.t.Concat(e2.t);                    e.f = e2.f;                    foreach (int k in e.t)                    {                        BackPatch(k, m);                    }                }                else                {                    e = e1;                    Before();                }            }            else            {                e = e1;            }        }        #endregion        #region 布尔项        private void BoolItem(ref E e)        {            E e1 = new E();            BoolFactor(ref e1);            if (error == "")            {                Next();                if (tokens[i].Code == 1)                {                    Next();                    int m = fps.Count;                    E e2 = new E();                    BoolItem(ref e2);                    e.t = e2.t;                    e.f.Concat(e1.f);                    e.f.Concat(e2.f);                    foreach (int k in e.t)                    {                        BackPatch(k, m);                    }                }                else                {                    e = e1;                    Before();                }            }        }        #endregion        #region 布尔因子        private void BoolFactor(ref E e)        {            if (tokens[i].Code == 10)            {                Next();                E e1 = new E();                BoolFactor(ref e1);                e.t = e1.f;                e.f = e1.t;            }            else            {                E e1 = new E();                BoolValue(ref e1);                e = e1;            }        }        #endregion        #region 布尔量        private void BoolValue(ref E e)        {            if (tokens[i].Code == 15 || tokens[i].Code == 7)            {                e.t.Add(fps.Count);                e.f.Add(fps.Count + 1);                tt = tokens[i].Name;            }            else if (tokens[i].Code == 18)            {                Next();                if (tokens[i].Code == 34 || tokens[i].Code == 33 || tokens[i].Code == 32 || tokens[i].Code == 37 || tokens[i].Code == 36 || tokens[i].Code == 35)                {                    Next();                    if (tokens[i].Code == 18)                    {                        e.t.Add(fps.Count);                        e.f.Add(fps.Count + 1);                        Emit("j" + tokens[i - 1].Name, tokens[i - 2].Name, tokens[i].Name, "-1");                        Emit("j", "_", "_", "-1");                    }                    else                    {                        Before();                    }                }                else                {                    Before();                    e.t.Add(fps.Count);                    e.f.Add(fps.Count + 1);                    Emit("jnz", tokens[i].Name, "_", "-1");                    Emit("j", "_", "_", "-1");                    Next();                }            }            else if (tokens[i].Code == 21)            {                E e1 = new E();                BoolExp(ref e1);                e.t = e1.t;                e.f = e1.f;                if (tokens[i].Code == 22)                {                    return;                }            }        }        #endregion        #region 算数表达式        private void AritExp()        {            Item();            if (error == "")            {                Next();                if (tokens[i].Code == 23 || tokens[i].Code == 24)                {                    string[] temp = { tokens[i - 1].Name, tokens[i].Name };                    if (tokens[i - 1].Code == 22)                    {                        temp[0] = tt;                    }                    Next();                    AritExp();                    Emit(temp[1], temp[0], tt, NewTemp());                    tt = "T" + (ti - 1).ToString();                }                else                {                    Before();                    return;                }            }            else            {                return;            }        }        #endregion        #region 项        private void Item()        {            Factor();            if (error == "")            {                Next();                if (tokens[i].Code == 25 || tokens[i].Code == 26)                {                    string[] temp = { tokens[i - 1].Name, tokens[i].Name };                    if (tokens[i - 1].Code == 22)                    {                        temp[0] = tt;                    }                    Next();                    Item();                    Emit(temp[1], temp[0], tt, NewTemp());                    tt = "T" + (ti - 1).ToString();                }                else                {                    Before();                }            }            else            {            }        }        #endregion        #region 因子        private void Factor()        {            if (tokens[i].Code == 21)            {                Next();                AritExp();                Next();                if (tokens[i].Code == 22)                {                }                else                {                    error = "因子中算数表达式缺少)";                }            }            else            {                CalQua();            }        }        #endregion        #region 算数量        private void CalQua()        {            if (tokens[i].Code == 18 || tokens[i].Code == 19 || tokens[i].Code == 20)            {                tt = tokens[i].Name;            }            else            {                error = "算数量出错";            }        }        #endregion        #region 结构句        private void StructSent(ref S s)        {            if (tokens[i].Code == 2)            {                Next();                ComSent();            }            else if (tokens[i].Code == 8)            {                Next();                IfSent(ref s);            }            else if (tokens[i].Code == 17)            {                Next();                WhileSent(ref s);            }        }        #endregion        #region if语句        private void IfSent(ref S s)        {            E e = new E();            BoolExp(ref e);            if (error == "")            {                Next();                if (tokens[i].Code == 14)                {                    int m1 = fps.Count;                    S s1 = new S();                    Next();                    ExecSent(ref s1);                    Next();                    if (tokens[i].Code == 5)                    {                        S n = new S();                        n.next.Add(fps.Count);                        Emit("j", "_", "_", "-1");                        S s2 = new S();                        int m2 = fps.Count;                        Next();                        ExecSent(ref s2);                        s.next=s1.next;                        s.next.Concat(n.next);                        s.next.Concat(s2.next);                        foreach (int k in e.t)                        {                            BackPatch(k, m1);                        }                        foreach (int k in e.f)                        {                            BackPatch(k, m2);                        }                    }                    else                    {                        s.next=e.f;                        s.next.Concat(s1.next);                        foreach (int k in e.t)                        {                            BackPatch(k, m1);                        }                        Before();                    }                }                else                {                    error = "if...then语句缺少then";                }            }            else            {                error = "if语句布尔表达式出错";            }        }        #endregion        #region while语句        private void WhileSent(ref S s)        {            int m1 = fps.Count;            E e = new E();            BoolExp(ref e);            Next();            if (tokens[i].Code == 4)            {                int m2 = fps.Count;                S s1 = new S();                Next();                ExecSent(ref s1);                s.next = e.f;                Emit("j", "_", "_", m1.ToString());                foreach (int k in e.t)                {                    BackPatch(k, m2);                }                foreach (int k in s1.next)                {                    BackPatch(k, m1);                }            }        }        #endregion    }}
FourPart.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 编译{    public class FourPart    {        public string Op { get; set; }        public string StrLeft { get; set; }        public string StrRight { get; set; }        public string JumpNum { get; set; }        public bool Input { get; set; }        public FourPart() { }        public FourPart(string op, string strLeft, string strRight, string jumpNum)        {            this.Op = op;            this.StrLeft = strLeft;            this.StrRight = strRight;            this.JumpNum = jumpNum;            this.Input = false;        }    }}
Create.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 编译{    public class Create    {        List<FourPart> fps = new List<FourPart>();        public List<symble> symbles = new List<symble>();        public List<Assembly> assemblys = new List<Assembly>();        string bx = "";        string dx = "";        bool ism = false;        public Create(Semantic s)        {            fps = s.fps;            symbles = s.symbles;            Dispose();            Back();            Translate();        }        #region 从尾到头的回填待用,活跃信息        private void Back()        {            int i = fps.Count - 2;            for (; i == 0; i--)            {                if (!fps[i].Op.Contains("j"))                {                    string str = fps[i].StrLeft;                    foreach (symble s in symbles)                    {                        if (s.Name == str)                        {                            s.Wait.Add(new string[2] { "" + i + 1 + "", "Y" });                        }                    }                    if (fps[i].StrRight != "_")                    {                        str = fps[i].StrRight;                        foreach (symble s in symbles)                        {                            if (s.Name == str)                            {                                s.Wait.Add(new string[2] { "" + i + 1 + "", "Y" });                            }                        }                    }                }            }        }        #endregion        #region 划分基本块        private void Dispose()        {            fps[1].Input = true;            int i = 0;            foreach (FourPart f in fps)            {                if (f.Op.Contains("j") && f.JumpNum != "-1")                {                    fps[Convert.ToInt32(f.JumpNum)].Input = true;                    if (f.Op != "j")                    {                        fps[i + 1].Input = true;                    }                }                i++;            }        }        #endregion        #region 寻找参数的value值        private string GetValue(string str)        {            foreach (symble s in symbles)            {                if (s.Name == str)                {                    return s.Value;                }            }            return "";        }        #endregion        #region 寄存器分配策略        private string GetReg(FourPart f)        {            if (bx == "" || GetValue(f.StrLeft) == "bx")            {                bx = f.StrLeft;                foreach (symble s in symbles)                {                    if (s.Name == f.StrLeft)                    {                        s.Value = "bx";                    }                }                return "bx";            }            else            {                if (dx == "" || GetValue(f.StrLeft) == "dx")                {                    dx = f.StrLeft;                    foreach (symble s in symbles)                    {                        if (s.Name == f.StrLeft)                        {                            s.Value = "dx";                        }                    }                    return "dx";                }                else                {                    ism = true;                    int bxNum = 0;                    int dxNum = 0;                    foreach (symble s in symbles)                    {                        if (s.Name == bx)                        {                            bxNum = Convert.ToInt32(s.Wait.Last()[0]);                        }                        if (s.Name == dx)                        {                            dxNum = Convert.ToInt32(s.Wait.Last()[0]);                        }                    }                    if (bxNum > dxNum)                    {                        dx = f.StrLeft;                        foreach (symble s in symbles)                        {                            if (s.Name == f.StrLeft)                            {                                s.Value = "dx";                            }                        }                        return "dx";                    }                    else                    {                        bx = f.StrLeft;                        foreach (symble s in symbles)                        {                            if (s.Name == f.StrLeft)                            {                                s.Value = "bx";                            }                        }                        return "bx";                    }                }            }        }        #endregion        #region 寄存器内信息不再用清空        private void SetNull()        {            if (bx != "")            {                foreach (symble sym in symbles)                {                    if (sym.Name == bx)                    {                        if (sym.Wait.Count == 0)                        {                            bx = "";                        }                    }                }            }            if (dx != "")            {                foreach (symble sym in symbles)                {                    if (sym.Name == dx)                    {                        if (sym.Wait.Count == 0)                        {                            dx = "";                        }                    }                }            }        }         #endregion        #region 放入主存        private void PutIntoM(string s)        {            if (ism)            {                Assembly a;                if (s == "bx")                {                    a = new Assembly("MOV", bx, s);                }                else                {                    a = new Assembly("MOV", dx, s);                }                assemblys.Add(a);                ism = false;            }        }         #endregion        #region 删除代码执行后对应的待用非待用信息        private void DelateWait(FourPart f)        {            foreach (symble sym in symbles)            {                if (sym.Name == f.StrLeft)                {                    if (sym.Wait.Count > 1)                    {                        sym.Wait.RemoveAt(sym.Wait.Count - 1);                    }                }                if (sym.Name == f.StrRight)                {                    if (sym.Wait.Count > 1)                    {                        sym.Wait.RemoveAt(sym.Wait.Count - 1);                    }                }            }        }         #endregion        #region 产生目标代码        private void Translate()        {            int i = 0;            foreach (FourPart f in fps)            {                if (f.Op == "j")                {                    Assembly a = new Assembly("JMP", "L" + f.JumpNum, "");                    a.Num = i.ToString();                    assemblys.Add(a);                    SetNull();                }                else if (f.Op == "j>")                {                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", bx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", dx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("CMP", s, f.StrRight);                        assemblys.Add(a2);                    }                    Assembly a3 = new Assembly("JG", "L" + f.JumpNum, "");                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "j<")                {                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", bx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", dx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("CMP", s, f.StrRight);                        assemblys.Add(a2);                    }                    Assembly a3 = new Assembly("JL", "L" + f.JumpNum, "");                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "j=")                {                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", bx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", dx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("CMP", s, f.StrRight);                        assemblys.Add(a2);                    }                    Assembly a3 = new Assembly("JZ", "L" + f.JumpNum, "");                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "j<>")                {                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", bx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", dx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("CMP", s, f.StrRight);                        assemblys.Add(a2);                    }                    Assembly a3 = new Assembly("JNZ", "L" + f.JumpNum, "");                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "j<=")                {                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", bx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", dx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("CMP", s, f.StrRight);                        assemblys.Add(a2);                    }                    Assembly a3 = new Assembly("JLE", "L" + f.JumpNum, "");                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "j>=")                {                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", bx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("CMP", dx, f.StrRight);                        a1.Num = i.ToString();                        assemblys.Add(a1);                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("CMP", s, f.StrRight);                        assemblys.Add(a2);                    }                    Assembly a3 = new Assembly("JGE", "L" + f.JumpNum, "");                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "+")                {                    string reg = "";                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("ADD", bx, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        reg = "bx";                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("ADD", dx, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        reg = "dx";                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("ADD", s, f.StrRight);                        assemblys.Add(a2);                        reg = s;                    }                    Assembly a3 = new Assembly("MOV", f.JumpNum, reg);                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "-")                {                    string reg = "";                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("SUB", bx, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        reg = "bx";                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("SUB", dx, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        reg = "dx";                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("SUB", s, f.StrRight);                        assemblys.Add(a2);                        reg = s;                    }                    Assembly a3 = new Assembly("MOV", f.JumpNum, reg);                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "*")                {                    string reg = "";                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("MUL", bx, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        reg = "bx";                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("MUL", dx, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        reg = "dx";                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("MUL", s, f.StrRight);                        assemblys.Add(a2);                        reg = s;                    }                    Assembly a3 = new Assembly("MOV", f.JumpNum, reg);                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == "/")                {                    string reg = "";                    if (bx == f.StrLeft)                    {                        Assembly a1 = new Assembly("DIV", bx, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        reg = "bx";                    }                    else if (dx == f.StrLeft)                    {                        Assembly a1 = new Assembly("DIV", dx, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        reg = "dx";                    }                    else                    {                        string s = GetReg(f);                        PutIntoM(s);                        Assembly a1 = new Assembly("MOV", s, f.StrLeft);                        a1.Num = i.ToString();                        assemblys.Add(a1);                        Assembly a2 = new Assembly("DIV", s, f.StrRight);                        assemblys.Add(a2);                        reg = s;                    }                    Assembly a3 = new Assembly("MOV", f.JumpNum, reg);                    assemblys.Add(a3);                    DelateWait(f);                    SetNull();                }                else if (f.Op == ":=")                {                    Assembly a1 = new Assembly("MOV", f.JumpNum, f.StrLeft);                    a1.Num = i.ToString();                    assemblys.Add(a1);                    foreach (symble sym in symbles)                    {                        if (sym.Name == f.StrLeft)                        {                            if (sym.Wait.Count > 1)                            {                                sym.Wait.RemoveAt(sym.Wait.Count - 1);                            }                        }                    }                    SetNull();                }                else                {                }                i++;            }        }        #endregion    }}








0 0