用C#实现的简单PL0 to C编译器
作者:yxin1322
blog:
http://blog.csdn.net/yxin1322
转载请注明出处
这个程序是我《编译原理》的期末大作业,要求实现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(
new WordTableEntry(Word_Type.Reserved_Words,str1));
149
else if(GETSYM.IsIdentifier(str1))
150 WordTable.Add(
new WordTableEntry(Word_Type.Identifier,str1));
151
else
152 {
153
string error=
"Error Accur in Line:"+LineNum+
" '"+str1+
"'不是合法的单词";
154 ErrorList.Add(error);
155 }
156
157 }
158
159
// System.Console.WriteLine(Line);
160 Line=sr.ReadLine();
161 LineNum++;
162 }
163
164 }
165 sr.Close();
166 }
167
if(ErrorList.Count==
0)
168
return true;
169
else
170 {
171
for(
int i=
0;i<ErrorList.Count;i++)
172 Console.WriteLine((
string)ErrorList[i]);
173
return false;
174 }
175 }
176
177
public static bool IsBound_Operator(
string a)
178 {
179
foreach(
string str
in Bound_OperatorList)
180 {
181
if(a.Equals(str))
182
return true;
183 }
184
return false;
185 }
186
187
public static bool IsOperator(
ref string a,
string b,
ref int c)
188 {
189
string tem=a+b;
190
foreach(
string str
in OperatorList)
191 {
192
if(tem.Equals(str))
193 {
194 a=a+b;
195 c++;
196
return true;
197 }
198 }
199
foreach(
string str
in OperatorList)
200 {
201
if(a.Equals(str))
202
return true;
203 }
204
return false;
205
206 }
207
208
public static bool IsReserved_Words(
string a)
209 {
210
foreach(
string str
in Reserved_WordsList)
211 {
212
if((a.ToUpper()).Equals(str))
213
return true;
214 }
215
return false;
216 }
217
218
public static bool IsNumber(
string str)
219 {
220 Regex r=
new Regex(@
"^/d+$");
221
if(r.IsMatch(str))
222
return true;
223
else
224
return false;
225 }
226
public static bool IsIdentifier(
string str)
227 {
228 Regex r=
new Regex(@
"^[a-zA-Z][a-zA-Z0-9]*$");
229
if(r.IsMatch(str))
230
return true;
231
else
232
return false;
233
234 }
235
236 }
237 }
WordTableEntry.CS
1
/* code by: yxin1322
2 date: 2005.6
3 blog: http://blog.csdn.net/yxin1322
4 Email: yxin1322@gmail.com
5 */
6
7
using System;
8
9
//字符串类型定义
10
public enum Word_Type{Reserved_Words,Number,
Operator,Bound_Operator,Identifier,other}
11
namespace GETSYM
12 {
13
14
15
/// <summary>
16
/// WordTalbeEntry定义一个词汇表的节点
17
/// </summary>
18
public class WordTableEntry
19 {
20
21
22
23
private Word_Type wordtype;
//单词种类
24
private string word;
//单词值
25
26
public WordTableEntry()
//默认构造函数
27 {
28 wordtype=Word_Type.other;
29 word=
"";
30 }
31
32
public WordTableEntry(Word_Type a,
string b)
//带参数的构造函数
33 {
34 wordtype=a;
35 word=b;
36 }
37
38
public string Word
//属性
39 {
40 get
41 {
42
return word;
43 }
44 set
45 {
46 word=value;
47 }
48 }
49
50
public Word_Type WordType
//属性
51 {
52 get
53 {
54
return wordtype;
55 }
56 set
57 {
58 wordtype=value;
59 }
60 }
61
62
63 }
64 }
语法制导翻译及输出模块:为了翻译的简便,我采用了语法制导翻译的方式,即一边进行语法分析,一边将pl0语言翻译成C语言,若遇到语法错误则停止翻译,报告错误。在实现方式上采用了递归子程序法,递归子程序法简单直观,只要分析出了pl0语言的语法范式(EBNF),就能为每个范式构造对应的子程序。这里我已经得到了pl0语言的EBNF,如下:
〈程序〉∷=〈分程序〉.
〈分程序〉∷=[〈常量说明部分〉][〈变量说明部分〉][〈过程说明部分〉]〈语句〉
〈常量说明部分〉∷=CONST〈常量定义〉 {,〈常量定义〉};
〈常量定义〉∷=〈标识符〉=〈无符号整数〉
〈无符号整数〉∷=〈数字〉{〈数字〉}
〈变量说明部分〉∷=VAR〈标识符〉{,〈标识符〉};
〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}
〈过程说明部分〉∷=〈过程首部〉〈分程序〉{;〈过程说明部分〉};
〈过程首部〉∷=PROCEDURE〈标识符〉;
〈语句〉∷=〈赋值语句〉|〈条件语句〉|〈当型循环语句〉|
〈过程调用语句〉|〈读语句〉|〈写语句〉|〈复合语句〉|〈空〉
〈赋值语句〉∷=〈标识符〉∶=〈表达式〉
〈复合语句〉∷=BEGIN〈语句〉{;〈语句〉}END
〈条件〉∷=〈表达式〉〈关系运算符〉〈表达式〉|ODD〈表达式〉
〈表达式〉∷=[+|-]〈项〉{〈加法运算符〉〈项〉}
〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}
〈因子〉∷=〈标识符〉|〈无符号整数〉|'('〈表达式〉')'
〈加法运算符〉∷=+|-
〈乘法运算符〉∷=*|/
〈关系运算符〉∷=#|=|<|<=|>|>=
〈条件语句〉∷=IF〈条件〉THEN〈语句〉
〈过程调用语句〉∷=CALL〈标识符〉
〈当型循环语句〉∷=WHILE〈条件〉DO〈语句〉
〈读语句〉∷=READ'('〈标识符〉{,〈标识符〉}')'
〈写语句〉∷=WRITE'('〈表达式〉{,〈表达式〉}')'
〈字母〉∷=a|b|…|X|Y|Z
〈数字〉∷=0|1|2|…|8|9
根据EBNF就可以很快写出语法分析和翻译程序,代码如下:
1
/*------------------------------------------------------------
2 <pl0 to C Convertor v0.1> Copyright 2005
3 code by: yxin1322
4 date: 2005.6
5 blog: http://blog.csdn.net/yxin1322
6 Email: yxin1322@gmail.com
7 运行环境:.Net FrameWork 1.1
8 --------------------------------------------------------------*/
9
10
using System;
11
using System.
Collections;
12
using System.
IO;
13
using System.
Text.
RegularExpressions;
14
using GETSYM;
15
16
namespace Pascal_to_C_Convertor
17 {
18
/// <summary>
19
/// Pascal_to_C 的摘要说明。
20
/// 进行Pascal到C转换的实现类
21
/// </summary>
22
public class Pascal_to_C
23 {
24
private string pascal_file_name;
//pascal源文件名
25
static private int word_count;
//分析pascal单词表的记数器
26
private ArrayList pascal_word_table;
27
public ArrayList C_Source;
//存储转换好的C语言源程序
28
public ArrayList ErrorList;
29
30
31
public Pascal_to_C()
32 {
33
this.pascal_file_name=
"";
34 word_count=-
1;
//初始值为-1
35
this.pascal_word_table=
new ArrayList();
36
this.C_Source=
new ArrayList();
37
this.ErrorList=
new ArrayList();
38
39 }
40
41
public Pascal_to_C(
string filename)
42 {
43
this.PascalFileName=filename;
44 word_count=-
1;
//初始值为-1
45
this.pascal_word_table=
new ArrayList();
46
this.C_Source=
new ArrayList();
47
this.ErrorList=
new ArrayList();
48 }
49
50
public string PascalFileName
51 {
52 get{
return this.pascal_file_name;}
53 set{
this.pascal_file_name=value;}
54 }
55
56
//获得分解好的PASCAL单词表
57
private ArrayList LoadWordTableFromFile()
58 {
59 GETSYM.GETSYM gs=
new GETSYM.GETSYM(
this.PascalFileName);
60
if(gs.getSYM())
61
return gs.WordTable;
62
else
63
return null;
64 }
65
66
public bool CreateCSourceCode()
67 {
68
this.pascal_word_table=
this.LoadWordTableFromFile();
//得到pl0单词表
69
70
if(
this.pascal_word_table==
null)
//词法分析出错
71 {
72
return false;
73 }
74
this.pascal_word_table.Add(
new WordTableEntry(Word_Type.other,
"####"));
//添加单词表尾
75
76 WordTableEntry w=
this.getNextWord();
77
78
System.Console.WriteLine(
"/n正在进行语法分析...");
79
80
this.Program(
ref w);
//调用递归分析程序
81
if(word_count==
this.pascal_word_table.Count-
1 && ErrorList.Count==
0)
82 {
83
return true;
84 }
85
else
86 {
87
this.PrintErrorList();
//打印错误列表
88
return false;
89 }
90 }
91
92
//得到pascal单词表的下一个单词
93
private WordTableEntry getNextWord()
94 {
95 word_count++;
96
return ((WordTableEntry)
this.pascal_word_table[word_count]);
97 }
98
99
//递归子程序从次开始
100
101
//"程序"递归程序
102
//〈程序〉∷=〈分程序〉.
103
private void Program(
ref WordTableEntry w)
104 {
105 Subprogram(
ref w);
106
if(!w.Word.Equals(
"."))
107 {
108 ErrorList.Add(
"分程序结束期待一个.");
109 }
110
else
111 {
112
this.C_Source.Add(
"/n");
113
114 w=
this.getNextWord();
115 }
116
117 }
118
119
//"分程序"递归程序
120
//〈分程序〉∷=[〈常量说明部分〉][〈变量说明部分〉][〈过程说明部分〉]〈语句〉
121
private void Subprogram(
ref WordTableEntry w)
122 {
123
if(w.Word.ToUpper().Equals(
"CONST"))
124
this.ConstValueExplain(
ref w);
125
if(w.Word.ToUpper().Equals(
"VAR"))
126
this.VariableExplain(
ref w);
127
if(w.Word.ToUpper().Equals(
"PROCEDURE"))
128
this.ProcedureExplain(
ref w);
129
this.Sentence(
ref w);
130
131 }
132
133
//"常量说明部分"递归程序
134
//〈常量说明部分〉∷=CONST〈常量定义〉 {,〈常量定义〉};
135
private void ConstValueExplain(
ref WordTableEntry w)
136 {
137
if(w.Word.ToUpper().Equals(
"CONST"))
138 {
139
this.C_Source.Add(
"const int");
140
141 w=
this.getNextWord();
142
this.ConstValue(
ref w);
143
while(w.Word.ToUpper().Equals(
","))
144 {
145
this.C_Source.Add(
",");
146
147 w=
this.getNextWord();
148
this.ConstValue(
ref w);
149 }
150
if(!w.Word.Equals(
";"))
151 {
152 ErrorList.Add(
"常量定义后没有加分号!");
153 }
154
else
155 {
156
this.C_Source.Add(
";/n");
157 w=
this.getNextWord();
158 }
159
160 }
161 }
162
163
//"常量定义"递归程序
164
//〈常量定义〉∷=〈标识符〉=〈无符号整数〉
165
private void ConstValue(
ref WordTableEntry w)
166 {
167
this.Identifier(
ref w);
168
169
if(w.Word.Equals(
"="))
170 {
171
this.C_Source.Add(
"=");
172
173 w=
this.getNextWord();
174
this.UnsignedNumber(
ref w);
175 }
176
else
177 {
178
this.ErrorList.Add(
"变量定义缺少等号!");
179 }
180 }
181
182
//"无符号整数"递归程序
183
//〈无符号整数〉∷=〈数字〉{〈数字〉}
184
private void UnsignedNumber(
ref WordTableEntry w)
185 {
186
if(w.WordType==Word_Type.Number)
187 {
188
this.C_Source.Add(w.Word);
189
190 w=
this.getNextWord();
191 }
192
else
193 ErrorList.Add(
"期望一个无符号整数!");
194 }
195
196
//"变量说明部分"递归程序
197
//〈变量说明部分〉∷=VAR〈标识符〉{,〈标识符〉};
198
private void VariableExplain(
ref WordTableEntry w)
199 {
200
if(w.Word.ToUpper().Equals(
"VAR"))
201 {
202
this.C_Source.Add(
"int");
203
204 w=
this.getNextWord();
205
this.Identifier(
ref w);
206
while(w.Word.ToUpper().Equals(
","))
207 {
208
this.C_Source.Add(
",");
209
210 w=
this.getNextWord();
211
this.Identifier(
ref w);
212 }
213
if(!w.Word.Equals(
";"))
214 {
215 ErrorList.Add(
"变量定义后没有加分号!");
216 }
217
else
218 {
219
this.C_Source.Add(
";/n");
220
221 w=
this.getNextWord();
222 }
223
224 }
225 }
226
227
//"标识符"递归程序
228
//〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}
229
private void Identifier(
ref WordTableEntry w)
230 {
231
if (w.WordType==Word_Type.Identifier)
232 {
233
this.C_Source.Add(w.Word);
234
235 w=
this.getNextWord();
236 }
237
else
238 {
239 ErrorList.Add(
"期望一个标识符!");
240 }
241 }
242
243
//"过程说明部分"递归程序
244
//〈过程说明部分〉∷=〈过程首部〉〈分程序〉{;〈过程说明部分〉};
245
private void ProcedureExplain(
ref WordTableEntry w)
246 {
247
this.ProcedureHead(
ref w);
248
249
this.C_Source.Add(
"{");
250
251
this.Subprogram(
ref w);
252
while(w.Word.Equals(
";"))
253 {
254
this.C_Source.Add(
";/n");
255
256 w=
this.getNextWord();
257
this.ProcedureExplain(
ref w);
258 }
259
if (!w.Word.Equals(
";"))
260 {
261 ErrorList.Add(
"过程的结束没有加分号!");
262 }
263
else
264 {
265
this.C_Source.Add(
";}/n");
266
267 w=
this.getNextWord();
268 }
269 }
270
271
//"过程首部"递归程序
272
//〈过程首部〉∷=PROCEDURE〈标识符〉;
273
private void ProcedureHead(
ref WordTableEntry w)
274 {
275
if(w.Word.ToUpper().Equals(
"PROCEDURE"))
276 {
277
this.C_Source.Add(
"void");
278
279 w=
this.getNextWord();
280
this.Identifier(
ref w);
281
if (!w.Word.Equals(
";"))
282 {
283 ErrorList.Add(
"过程名后缺少分号!");
284 }
285
else
286 {
287
this.C_Source.Add(
"()/n");
288 w=
this.getNextWord();
289 }
290 }
291
else
292 ErrorList.Add(
"过程需要从关键字PROCEDURE开始!");
293 }
294
295
//"语句"递归程序
296
//〈语句〉∷=〈赋值语句〉|〈条件语句〉|〈当型循环语句〉|〈过程调用语句〉|〈读语句〉|〈写语句〉|〈复合语句〉|〈空〉
297
private void Sentence(
ref WordTableEntry w)
298 {
299
if (w.WordType==Word_Type.Identifier)
300 {
301
this.EvaluateSentence(
ref w);
302 }
303
else if (w.Word.ToUpper().Equals(
"IF"))
304 {
305
this.ConditionSentence(
ref w);
306 }
307
else if (w.Word.ToUpper().Equals(
"WHILE"))
308 {
309
this.WhileSentence(
ref w);
310 }
311
else if (w.Word.ToUpper().Equals(
"CALL"))
312 {
313
this.WhileSentence(
ref w);
314 }
315
else if (w.Word.ToUpper().Equals(
"READ"))
316 {
317
this.ReadSentence(
ref w);
318 }
319
else if (w.Word.ToUpper().Equals(
"WRITE"))
320 {
321
this.WriteSentence(
ref w);
322 }
323
else if (w.Word.ToUpper().Equals(
"BEGIN"))
324 {
325
this.ComplexSentence(
ref w);
326 }
327
else
328 {
329 ;
330 }
331 }
332
333
//"赋值语句"递归程序
334
//〈赋值语句〉∷=〈标识符〉∶=〈表达式〉
335
private void EvaluateSentence(
ref WordTableEntry w)
336 {
337
this.Identifier(
ref w);
338
if (w.Word.Equals(
":="))
339 {
340
this.C_Source.Add(
"=");
341
342 w=
this.getNextWord();
343
this.Expression(
ref w);
344 }
345
else
346 ErrorList.Add(
"赋值语句缺少等号!");
347 }
348
349
//"复合语句"递归程序
350
//〈复合语句〉∷=BEGIN〈语句〉{;〈语句〉}END
351
private void ComplexSentence(
ref WordTableEntry w)
352 {
353
if (w.Word.ToUpper().Equals(
"BEGIN"))
354 {
355
this.C_Source.Add(
"{/n");
356
357 w=
this.getNextWord();
358
this.Sentence(
ref w);
359
while(w.Word.Equals(
";"))
360 {
361
this.C_Source.Add(
";/n");
362
363 w=
this.getNextWord();
364
this.Sentence(
ref w);
365 }
366
367
this.C_Source.Add(
";/n");
368
369
if (!w.Word.ToUpper().Equals(
"END"))
370 {
371 ErrorList.Add(
"缺少END标识符!");
372 }
373
else
374 {
375
this.C_Source.Add(
"}/n");
376
377 w=
this.getNextWord();
378 }
379 }
380
381 }
382
383
//"条件"递归程序
384
//〈条件〉∷=〈表达式〉〈关系运算符〉〈表达式〉|ODD〈表达式〉
385
private void Condition(
ref WordTableEntry w)
386 {
387
if ((w.Word.Equals(
"+") || w.Word.Equals(
"-")) || w.WordType==Word_Type.Identifier)
388 {
389
this.Expression(
ref w);
390
this.RelationSymbol(
ref w);
391
this.Expression(
ref w);
392 }
393
else if (w.Word.ToUpper().Equals(
"ODD"))
394 {
395
this.C_Source.Add(
"(");
396
397 w=
this.getNextWord();
398
this.Expression(
ref w);
399
400
this.C_Source.Add(
")%2==1");
401 }
402
else
403 ErrorList.Add(
"条件表达式错误!");
404 }
405
406
//"表达式"递归程序
407
//〈表达式〉∷=[+|-]〈项〉{〈加法运算符〉〈项〉}
408
private void Expression(
ref WordTableEntry w)
409 {
410
if (w.Word.Equals(
"+"))
411 {
412
this.C_Source.Add(
"+");
413
414 w=
this.getNextWord();
415 }
416
else if (w.Word.Equals(
"-"))
417 {
418
this.C_Source.Add(
"-");
419
420 w=
this.getNextWord();
421 }
422
else
423 {
424 ;
425 }
426
this.ExpressionItem(
ref w);
427
while (w.Word.Equals(
"+") || w.Word.Equals(
"-"))
428 {
429
this.AdditiveSymbol(
ref w);
430
this.ExpressionItem(
ref w);
431 }
432 }
433
434
//"项"递归程序
435
//〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}
436
private void ExpressionItem(
ref WordTableEntry w)
437 {
438
this.Gene(
ref w);
439
while (w.Word.Equals(
"*") || w.Word.Equals(
"/"))
440 {
441
this.MultiplicativeSymbol(
ref w);
442
this.Gene(
ref w);
443 }
444 }
445
446
//"因子"递归程序
447
//〈因子〉∷=〈标识符〉|〈无符号整数〉|'('〈表达式〉')'
448
private void Gene(
ref WordTableEntry w)
449 {
450
if (w.WordType==Word_Type.Identifier)
451 {
452
453
this.Identifier(
ref w);
454 }
455
else if (w.WordType==Word_Type.Number)
456 {
457
458
this.UnsignedNumber(
ref w);
459 }
460
else if (w.Word.Equals(
"("))
461 {
462
this.C_Source.Add(
"(");
463
464 w=
this.getNextWord();
465
this.Expression(
ref w);
466
if (!w.Word.Equals(
")"))
467 {
468 ErrorList.Add(
"表达式括号不匹配!");
469 }
470
else
471 {
472
this.C_Source.Add(
")");
473
474 w=
this.getNextWord();
475 }
476 }
477
else
478 ErrorList.Add(
"表达式错误!");
479 }
480
481
//"加法运算符"递归程序
482
//〈加法运算符〉∷=+|-
483
private void AdditiveSymbol(
ref WordTableEntry w)
484 {
485
if (w.Word.Equals(
"+") || w.Word.Equals(
"-"))
486 {
487
this.C_Source.Add(w.Word);
488
489 w=
this.getNextWord();
490 }
491
else
492 ErrorList.Add(
"缺少加减法运算符!");
493 }
494
495
//"乘法运算符"递归程序
496
//〈乘法运算符〉∷=*|/
497
private void MultiplicativeSymbol(
ref WordTableEntry w)
498 {
499
if (w.Word.Equals(
"*") || w.Word.Equals(
"/"))
500 {
501
this.C_Source.Add(w.Word);
502
503 w=
this.getNextWord();
504 }
505
else
506 ErrorList.Add(
"缺少乘除法运算符!");
507 }
508
509
//"关系运算符"递归程序
510
//〈关系运算符〉∷=#|=|<|<=|>|>=
511
private void RelationSymbol(
ref WordTableEntry w)
512 {
513
if (w.Word.Equals(
"#") || w.Word.Equals(
"="))
514 {
515
this.C_Source.Add(w.Word);
516
517 w=
this.getNextWord();
518 }
519
else if (w.Word.Equals(
"<") || w.Word.Equals(
"<="))
520 {
521
this.C_Source.Add(w.Word);
522
523 w=
this.getNextWord();
524 }
525
else if (w.Word.Equals(
">") || w.Word.Equals(
">="))
526 {
527
this.C_Source.Add(w.Word);
528
529 w=
this.getNextWord();
530 }
531
else
532 ErrorList.Add(
"缺少关系运算符!");
533 }
534
535
//"条件语句"递归程序
536
//〈条件语句〉∷=IF〈条件〉THEN〈语句〉
537
private void ConditionSentence(
ref WordTableEntry w)
538 {
539
if (w.Word.ToUpper().Equals(
"IF"))
540 {
541
this.C_Source.Add(
"if(");
542
543 w=
this.getNextWord();
544
this.Condition(
ref w);
545
546
this.C_Source.Add(
")/n");
547
548
if (w.Word.ToUpper().Equals(
"THEN"))
549 {
550
this.C_Source.Add(
"{/n");
551
552 w=
this.getNextWord();
553
this.Sentence(
ref w);
554
555
this.C_Source.Add(
";/n}/n");
556 }
557
else
558 ErrorList.Add(
"IF语句缺少THEN子句!");
559 }
560
else
561 ErrorList.Add(
"条件语句缺少IF!");
562 }
563
564
//"过程调用语句"递归程序
565
//〈过程调用语句〉∷=CALL〈标识符〉
566
private void ProcedureCall(
ref WordTableEntry w)
567 {
568
if(w.Word.ToUpper().Equals(
"CALL"))
569 {
570 w=
this.getNextWord();
571
this.Identifier(
ref w);
572
573
this.C_Source.Add(
"();/n");
574 }
575
576 }
577
578
//"当型循环语句"递归程序
579
//〈当型循环语句〉∷=WHILE〈条件〉DO〈语句〉
580
private void WhileSentence(
ref WordTableEntry w)
581 {
582
if (w.Word.ToUpper().Equals(
"WHILE"))
583 {
584
this.C_Source.Add(
"while(");
585
586 w=
this.getNextWord();
587
this.Condition(
ref w);
588
589
this.C_Source.Add(
")/n");
590
591
if (w.Word.ToUpper().Equals(
"DO"))
592 {
593
this.C_Source.Add(
"{/n");
594
595 w=
this.getNextWord();
596
this.Sentence(
ref w);
597
598
this.C_Source.Add(
";/n}/n");
599 }
600
else
601 ErrorList.Add(
"WHILE语句缺少DO子句!");
602 }
603
else
604 ErrorList.Add(
"循环语句缺少WHILE!");
605 }
606
607
//"读语句"递归程序
608
//〈读语句〉∷=READ'('〈标识符〉{,〈标识符〉}')'
609
private void ReadSentence(
ref WordTableEntry w)
610 {
611
if (w.Word.ToUpper().Equals(
"READ"))
612 {
613 w=
this.getNextWord();
614
if (w.Word.Equals(
"("))
615 {
616 w=
this.getNextWord();
617
618
this.C_Source.Add(
"scanf(/"%d/
",&");
619
620
this.Identifier(
ref w);
621
this.C_Source.Add(
");/n");
622
623
while (w.Word.Equals(
","))
624 {
625
this.C_Source.Add(
"scanf(/"%d/
",&");
626
627 w=
this.getNextWord();
628
this.Identifier(
ref w);
629
630
this.C_Source.Add(
")");
631
632 }
633
if (!w.Word.Equals(
")"))
634 {
635 ErrorList.Add(
"READ语句括号不匹配!");
636 }
637
else
638 w=
this.getNextWord();
639 }
640
else
641 ErrorList.Add(
"READ语句缺少左括号!");
642 }
643 }
644
645
//"写语句"递归程序
646
//〈写语句〉∷=WRITE'('〈表达式〉{,〈表达式〉}')'
647
private void WriteSentence(
ref WordTableEntry w)
648 {
649
if (w.Word.ToUpper().Equals(
"WRITE"))
650 {
651 w=
this.getNextWord();
652
if (w.Word.Equals(
"("))
653 {
654
this.C_Source.Add(
"printf(/"%d//n/
",");
655
656 w=
this.getNextWord();
657
this.Expression(
ref w);
658
659
this.C_Source.Add(
");/n");
660
661
while (w.Word.Equals(
","))
662 {
663
this.C_Source.Add(
"printf(/"%d//n/
",");
664
665 w=
this.getNextWord();
666
this.Expression(
ref w);
667
668
this.C_Source.Add(
")");
669 }
670
if (!w.Word.Equals(
")"))
671 {
672 ErrorList.Add(
"WRITE语句括号不匹配!");
673 }
674
else
675 w=
this.getNextWord();
676 }
677
else
678 ErrorList.Add(
"WRITE语句缺少左括号!");
679 }
680 }
681
682
//***************递归子程序到此结束
683
684
//打印错误列表
685
private void PrintErrorList()
686 {
687
System.Console.WriteLine(
"/n-------------ErrorList-------------");
688
if(ErrorList.Count==
0)
689
System.Console.WriteLine(
"没有错误发生,编译顺利完成!");
690
for(
int i=
0;i<ErrorList.Count;i++)
691 {
692
System.Console.WriteLine(
"[error{0}]:{1}",i,(
string)ErrorList[i]);
693 }
694 }
695
696
//将转换好的c语言源程序写如文件
697
private void SaveToCFile()
698 {
699
if(
this.PascalFileName.Equals(
""))
700 {
701
System.Console.WriteLine(
"Unknown output file name!");
702
return ;
703 }
704
705
string temfilename=Regex.Replace(
this.PascalFileName,@
"./w+$",
"");
706
string OutPutFileName=temfilename+
".C";
707
708
System.
IO.StreamWriter sw=
null;
//创建输出文件
709
710 sw=File.CreateText(OutPutFileName);
711
712 sw.WriteLine("/*
------------------------------------------------------------");
713 sw.WriteLine(" pl0 to C Convertor v0.1 Copyright 2005 yxin1322");
714 sw.WriteLine(" C Source File: [{0}]",this.PascalFileName);
715 sw.WriteLine(" Create Time:{0}",System.DateTime.Now.ToString());
716 sw.WriteLine(" ------------------------------------------------------------*/");
717
718
System.Console.WriteLine(
"/n正在写入文件.../n");
719
720 sw.WriteLine(
"#include <stdio.h>");
//添加c文件头部
721 sw.WriteLine(
"main()/n{");
722
723
724
for(
int i=
0;i<this.C_Source.Count;i++)
725 {
726 sw.Write(
"{0} ",
this.C_Source[i]);
727 }
728 sw.WriteLine(
"}");
729 sw.Close();
730
731
732
System.Console.WriteLine(
"已经将C源程序写入文件:{0}",OutPutFileName);
733 }
734
735
public static void Main(
string[] args)
736 {
737
string pl0FileName;
738
if(args.Length==
0)
739 {
740
System.Console.WriteLine(
" ------------------------------------------------------------");
741
System.Console.WriteLine(
" <pl0 to C Convertor v0.1> Copyright 2005 yxin1322/n");
742
System.Console.WriteLine(
" 运行环境:.Net FrameWork 1.1");
743
System.Console.WriteLine(
" ------------------------------------------------------------");
744
745
System.Console.Write(
"请输入pl0文件的路径及文件名(*.pl0):");
746 pl0FileName=
System.Console.ReadLine();
747 }
748
else
749 {
750 pl0FileName=args[
0];
751 }
752
753
System.Console.WriteLine(pl0FileName);
754 Pascal_to_C p2c=
new Pascal_to_C(pl0FileName);
755
756
if(p2c.CreateCSourceCode())
757 p2c.SaveToCFile();
758
759
System.Console.ReadLine();
760 }
761 }
762 }
程序打包下载地址:
http://free5.ys168.com/?yxin1322