这个程序是我《编译原理》的期末大作业,要求实现PL0到C语言的编译器,其实叫翻译器更贴切点。程序的实现目标是能把具有基本Pascal语法的pl0语言源程序转换成C语言程序。pl0支持变量定义、条件语句、循环语句、赋值语句,变量的控制台输入与输出。翻译出的C语言程序需能被常见的C编译器编译通过。
本程序分为两大模块:词法分析模块和语法制导翻译及输出模块。
词法分析模块:通过程序指定一个由pl0语言编写的程序源文件,词法分析器能够将源文件内容分解为一组单词序列,并判别每个单词的所属类别(分别有运算符、分界符、关键字、变量名和数字),当遇到非法字符串时,能报出错误发生的位置。如果分析成功而未遇到任何错误,则词法分析器返回给编译程序一个单词集合,以用来做语法分析。每个单词存放在一个WordTableEntry结果中。
词法分析模块代码如下:
GETSYM.CS
1 /* 2 code by: yxin1322 3 date: 2005.6 4 blog: http://blog.csdn.net/yxin1322 5 Email: yxin1322@gmail.com 6 */ 7 8 9 using System; 10 using System.Collections; 11 using System.Text.RegularExpressions; 12 using System.IO; 13 14 namespace GETSYM 15 { 16 /// <summary> 17 /// 词法分析器类 18 /// </summary> 19 public class GETSYM 20 { 21 public static string[] OperatorList={ "+","-","*","/",":=","#", 22 ">=","<=","<",">","=","&&","||"}; //运算符列表,可以扩充 23 public static string[] Bound_OperatorList={ ",",".",";","(",")"}; //分界符列表,可以扩充 24 public static string[] Reserved_WordsList= 25 { "CONST","VAR","PROCEDURE","BEGIN","END","ODD","IF", 26 CALL","WHILE","READ","DO","WRITE","THEN"}; //关键字列表,可以扩充 27 28 29 public ArrayList WordTable; //存储词法分析后的单词列表,列表的元素是WordTableEntry的对象 30 private string pl0FilePath; //存储需要分析的pl0源文件路径 31 32 //默认构造函数 33 public GETSYM() 34 { 35 WordTable=new ArrayList(); 36 PL0FilePath=""; 37 } 38 39 //初始化文件路径的构造函数 40 public GETSYM(string filepath) 41 { 42 WordTable=new ArrayList(); 43 PL0FilePath=filepath; 44 } 45 46 //属性 47 public string PL0FilePath 48 { 49 get{ return pl0FilePath;} 50 set{pl0FilePath=value;} 51 } 52 53 //将分析好的单词表写入文件 54 public void WriteSYMToFile() 55 { 56 if(pl0FilePath.Equals("")) 57 { 58 System.Console.WriteLine("Unknown output file name!"); 59 return ; 60 } 61 62 string temfilename=Regex.Replace(PL0FilePath,@"./w+$",""); 63 string OutPutFileName=temfilename+".SYM"; 64 65 System.IO.StreamWriter sw=null;//创建输出文件 66 67 sw=File.CreateText(OutPutFileName); 68 69 sw.WriteLine("//------------------------------------------------------------"); 70 sw.WriteLine("//pl0语言词法分析器 v0.2 Copyright 2005 yxin1322"); 71 sw.WriteLine("//单词表创建自文件[{0}]",pl0FilePath); 72 sw.WriteLine("//生成时间:{0}",System.DateTime.Now.ToString()); 73 sw.WriteLine("//------------------------------------------------------------"); 74 75 System.Console.WriteLine("/n生成单词表.../n"); 76 for(int i=0;i<WordTable.Count;i++) 77 { 78 sw.WriteLine("{0,15}: {1,-15}",((WordTableEntry)WordTable[i]).WordType.ToString(), 79 ((WordTableEntry)WordTable[i]).Word); 80 } 81 sw.Close(); 82 83 System.Console.WriteLine("已经将单词写入文件:{0}",OutPutFileName); 84 } 85 86 //对pl0源文件进行分析,划分出单词并分析其类别,存储进WoedTable 87 public bool getSYM() 88 { 89 System.Console.WriteLine("------------------------------------------------------------"); 90 System.Console.WriteLine("[pl0语言词法分析器 v0.2] Copyright 2005 yxin1322"); 91 System.Console.WriteLine("------------------------------------------------------------"); 92 93 ArrayList ErrorList=new ArrayList(); 94 if(pl0FilePath.Equals("")) 95 { 96 System.Console.WriteLine("你没有指定源文件!"); 97 return false; 98 } 99 if(!File.Exists(pl0FilePath)) 100 { 101 System.Console.WriteLine("找不到指定源文件!"); 102 return false; 103 } 104 else 105 { 106 System.Console.WriteLine("正在对文件内容进行词法分析..."); 107 StreamReader sr=File.OpenText(PL0FilePath); 108 109 int LineNum=0; //对当前分析的行进行记数 110 string Line=sr.ReadLine();//读入第一行 111 112 LineNum++; 113 while(Line!=null) 114 { 115 if(Regex.IsMatch(Line,@"^//")) //忽略注释 116 { 117 Line=sr.ReadLine(); 118 LineNum++; 119 } 120 121 else 122 { 123 Line=Regex.Replace(Line,@"//.*$",""); 124 125 for(int i=0;i<OperatorList.Length;i++) //对运算符和界符两边添加空格 126 Line=Line.Replace(OperatorList[i]," "+OperatorList[i]+" "); 127 for(int i=0;i<Bound_OperatorList.Length;i++) 128 Line=Line.Replace(Bound_OperatorList[i]," "+Bound_OperatorList[i]+" "); 129 130 Line=Regex.Replace(Line,@"/s+"," ");//将多个空格替换成一个空格 131 Line=Line.Trim(); //去掉一行两边的空格 132 133 string [] WordSplit=Regex.Split(Line," ");//用空格分割字符串 134 for(int k=0;k<WordSplit.Length;k++)//遍历分割后的字符串 135 { 136 string str1=WordSplit[k]; 137 string str2=(k<WordSplit.Length-1)?WordSplit[k+1]:""; 138 139 if(str1.Equals("")) 140 continue; 141 if(GETSYM.IsOperator(ref str1,str2,ref k)) 142 WordTable.Add(new WordTableEntry(Word_Type.Operator,str1)); 143 else if(GETSYM.IsNumber(str1)) 144 WordTable.Add(new WordTableEntry(Word_Type.Number,str1)); 145 else if(GETSYM.IsBound_Operator(str1)) 146 WordTable.Add(new WordTableEntry(Word_Type.Bound_Operator,str1)); 147 else if(GETSYM.IsReserved_Words(str1)) 148 WordTable.Add(