实验内容
从磁盘中读取一个Test.txt文件,并编程实现词法分析器对其进行词法分析,结果保存到另外一个Result.txt文件。
C#实现
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public string path1 = "", path2 = "";//路径1,路径2
public Form1()
{
InitializeComponent();
}
private void ListViewer_Load(object sender, EventArgs e) //Load
{
this.button1.Enabled = false;
}
//保存结果
private void button1_Click_1(object sender, EventArgs e)
{
string[] stringTemp = new string[this.resultListBox1.Items.Count];
saveFileDialog1.Title = "请输入要保存的文件名";
saveFileDialog1.Filter = "文本文档(*.txt)|*.txt";
saveFileDialog1.OverwritePrompt = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
path2 = saveFileDialog1.FileName;
StreamWriter sw = new StreamWriter(path2);
for (int counter = 0; counter < this.resultListBox1.Items.Count; counter++)
sw.WriteLine(this.resultListBox1.Items[counter].ToString());
sw.Close();
sw.Dispose();
}
this.button1.Enabled = false;
}
//打开文件
private void openFiles_Click_1(object sender, EventArgs e)
{
openFileDialog1.InitialDirectory = "";
openFileDialog1.Title = "请选择文件";
openFileDialog1.FileName = "";
openFileDialog1.Filter = "文本文档(*.txt)|*.txt";
if (openFileDialog1.ShowDialog() != DialogResult.Cancel)
{
System.IO.StreamReader sr = new System.IO.StreamReader(openFileDialog1.FileName);
this.richTextBox1.Text = sr.ReadToEnd();
sr.Close();
sr.Dispose();
}
}
private void save()//自动保存结果
{
try
{
string stringTemp1 = this.richTextBox1.Text; //保存源文件
string date = DateTime.Now.ToString("HH-mm-ff");
string zipath1 = "TestData(" + date + ").txt";
path1 = Application.StartupPath + "\\Text\\" + zipath1;
StreamWriter sw1 = new StreamWriter(path1);
sw1.Write(stringTemp1);
//this.linkLabel1.Text = zipath1;
sw1.Close();
sw1.Dispose();
string zipath2 = "Result(" + date + ").txt";//保存分析结果
path2 = Application.StartupPath + "\\Text\\" + zipath2;
StreamWriter sw2 = new StreamWriter(path2);
for (int counter = 0; counter < this.resultListBox1.Items.Count; counter++)
sw2.WriteLine(this.resultListBox1.Items[counter].ToString());
sw2.Close();
sw2.Dispose();
}
catch
{
MessageBox.Show("保存失败, 请手动保存!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
this.button1.Enabled = true;
}
}
//词法分析
private void BeginToAnalyse_Click_1(object sender, EventArgs e)
{
if (MessageBox.Show("是否自动保存结果?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
//判断列表是否为空,否则清空列表
if (this.resultListBox1.Items.Count != 0)
this.resultListBox1.Items.Clear();
char[] getch = textToCharArray();//字符数组。
//将字符数组转换为词法分析的单词数组。
charArrayToStringArray(getch);
this.button1.Enabled = false;
}
else {
//判断列表是否为空,否则清空列表
if (this.resultListBox1.Items.Count != 0)
this.resultListBox1.Items.Clear();
char[] getch = textToCharArray();//字符数组。
//将字符数组转换为词法分析的单词数组。
charArrayToStringArray(getch);
this.button1.Enabled = true;
}
}
private char[] textToCharArray()//将Text中的字符串,存入一个字符数组中。
{
string stringTemp;
stringTemp = this.richTextBox1.Text;
char[] getch = stringTemp.ToCharArray();//要处理的字符都在getch这个数组中
return getch;
}
// 字符数组 到 单词数组 //将字符数组转换为字符串数组。
private void charArrayToStringArray(char[] getch)
{
int errorCounter = 0, rowCounter = 1;
//用这个字符串数组存放词法分析后得到的单词。
string[] stringArrange = { "" };
char charTemp = ' ', charTemp1 = ' ';
// 存放一个分析得到的单词
string stringSave = "";
string[] keywords = { "auto", "break", "case", "char", "const", "continue", "default", "do",
"double", "else", "enum", "extern", "float", "for", "goto", "if", "int", "long", "register",
"return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union",
"unsigned", "void", "volatile", "while" };//关键字32个(46) //标识符(47) //整数(48)
string[] sign = { "~", "+", "+=", "++", "-", "-=", "--", "*", "*=", "?:", "/", "//","/=", "%",
"%=", "&", "&&", "&=", "|", "||", "|=", "!", "!=", "^", "^=", "<", "<=", "<<", "<<=",
">", ">=", ">>", ">>=", "=", "==" };//运算符34个(0-33)
string[] fengefu = { "(", ")", "[", "]", ",", ";", "{", "}", "'", ".", "#" };//分隔符11个(34-45)
string[] Num = { "取反", "加", "加等于", "加加", "减", "减等于", "减减", "乘", "乘等于", "条件",
"除", "除等于", "求余", "求余等于", "按位与", "逻辑与", "按位与等于", "按位或", "逻辑或",
"按位或等于", "逻辑非", "不等于", "按位异或", "按位异或等于", "小于", "小于等于", "左移",
"左移等于", "大于", "大于等于", "右移", "右移等于", "等于", "恒等于", "左小括号", "右小括号",
"左中括号", "右中括号", "逗号", "分号", "左大括号", "右大括号", "单引号", "点运算符", "#号",
"关键字", "标识符", "数字" };//错误所在行-1
try//一次循环得到一个单词。
{
if (getch.Length == 0)
MessageBox.Show("请输入要处理的程序代码......", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
else
{
this.resultListBox1.Items.Add("————分析开始————");
this.resultListBox1.Items.Add("————第 " + rowCounter + " 行————");//打印第一行
//查找//l为标识符,d为数字,c为".",为1的时候
int l = 0, d = 0, c = 0;
for (int i = 0; i < getch.Length;)
{
charTemp = getch[i];
//标识符或者关键字或者数字
if (char.IsLetter(charTemp) || char.IsNumber(charTemp) || charTemp == '_' || charTemp == '.')
{
if (char.IsLetter(charTemp))//纯字母
l = 1;
else if (char.IsNumber(charTemp))//纯数字
d = 1;
else if (charTemp == '.')//小数点
c = 1;
int a = 0;
//统计标识符或者关键字或者数字的集合
stringSave = stringSave + charTemp.ToString();
try//如果下一字符不是同类
{
charTemp1 = getch[i + 1];
}
catch
{
a = 1;//处理结束
}
if (!(char.IsLetter(charTemp1) || char.IsNumber(charTemp1) || charTemp1 == '_' || charTemp1 == '.') || a == 1)
{
if (l == 1 && d == 0)//纯字母
{
if (c == 0)//不含"."的字母
{
int flag = 0; //关键字
for (int t = 0; t < keywords.Length; t++)
{
string si = keywords[t];
if (stringSave == si)
{
this.resultListBox1.Items.Add("关键字 , 46 , " + stringSave);
flag = 1;
break;
}
else
flag = 0;
}
if (flag == 0)//标识符
this.resultListBox1.Items.Add("标识符 , 47 , " + stringSave);
}
else if (c == 1)//含"."的字母
{
//标识符+.+标识符.
string str1 = stringSave.Substring(0, stringSave.LastIndexOf("."));
string str2 = stringSave.Substring(stringSave.LastIndexOf(".") + 1);
this.resultListBox1.Items.Add("标识符 , 47 , " + str1);
this.resultListBox1.Items.Add("点运算符 , 44 , .");
this.resultListBox1.Items.Add("标识符 , 47 , " + str2);
}
}//end if
else if (l == 0 && d == 1)//纯数字
this.resultListBox1.Items.Add("数字 , 47 , " + stringSave);
else if (l == 1 && d == 1)//数字与字母的组合
{
try//数字开头的标识符形如"12c"
{
int shu = Convert.ToInt32(stringSave.Substring(0, 1));
if (shu >= 0 && shu <= 9)//打印错误信息
{
this.resultListBox1.Items.Add("");
errorCounter++;//计算错误个数
}
else
this.resultListBox1.Items.Add("标识符 , 47 , " + stringSave);
}
catch//不是以数字开头的标识符
{
if (c == 0)//无"."的
this.resultListBox1.Items.Add("标识符 , 47 , " + stringSave);
else if (c == 1)//有"."的
{
try//"."后面每一个字母是数字
{
int shu = Convert.ToInt32(stringSave.Substring(stringSave.LastIndexOf(".") + 1, 1));
if (shu >= 0 && shu <= 9)//打印错误信息
{
this.resultListBox1.Items.Add("");
errorCounter++;//计算错误个数
}
else//标识符+.+标识符.
{
string str1 = stringSave.Substring(0, stringSave.LastIndexOf("."));
string str2 = stringSave.Substring(stringSave.LastIndexOf(".") + 1);
this.resultListBox1.Items.Add("标识符 , 47 , " + str1);
this.resultListBox1.Items.Add("点运算符 , 44 , .");
this.resultListBox1.Items.Add("标识符 , 47 ," + str2);
}
}
catch //标识符+.+标识符.
{
string str1 = stringSave.Substring(0, stringSave.LastIndexOf("."));
string str2 = stringSave.Substring(stringSave.LastIndexOf(".") + 1);
this.resultListBox1.Items.Add("标识符 , 47 , " + str1);
this.resultListBox1.Items.Add("点运算符 , 44 , .");
this.resultListBox1.Items.Add("标识符 , 47 ," + str2);
}//end catch
}//end else if
}//end catch
}//end else if
stringSave = "";//清空单词
l = d = c = 0;//清零
}//end if
}//end if
else//运算符或者分隔符
{
int a = 0;
//统计运算符或者分隔符的集合
stringSave = stringSave + charTemp.ToString();
int flag = 0; //分隔符
//对照分隔符 打到则flag = 1;
for (int t = 0; t < fengefu.Length; t++)
{
string si = fengefu[t];
if (stringSave == si) //显示分隔符
{
this.resultListBox1.Items.Add(Num[t + 34] + " , " + (t + 34) + " , " + stringSave);
flag = 1;
break;
}
else
flag = 0;
}
if (flag == 0)//不是分隔符
{
try//如果下一字符不是同类
{
charTemp1 = getch[i + 1];
}
catch
{
a = 1;//处理结束
}
string stringSave2 = charTemp1.ToString();
int flag2 = 0; //对照分隔符 ,查到则flag = 1;
for (int t = 0; t < fengefu.Length; t++)
{
string si = fengefu[t];
if (stringSave2 == si)
{
flag2 = 1;
break;
}
else
flag2 = 0;
}
//下一个字符不是同类则执行操作
if (char.IsLetter(charTemp1) || char.IsNumber(charTemp1) || charTemp1 == '_' || charTemp1 == '.' || flag2 == 1 || a == 1)
{
int flag1 = 0; //运算符
//对照运算符 打到则flag = 1;
for (int t = 0; t < sign.Length; t++)
{
string si = sign[t];
if (stringSave == si)
{
//显示运算符
this.resultListBox1.Items.Add(Num[t] + " , " + t + " , " + stringSave);
flag1 = 1;
break;
}
else
flag1 = 0;
}
//不是运算符,则为分隔符
if (flag1 == 0 && charTemp != ' ' && charTemp != '\n' && charTemp != '\r')
{
//打印错误信息
this.resultListBox1.Items.Add("");
errorCounter++;//计算错误个数
}
stringSave = "";//清空单词
}//不是运算符,也不是分隔符,则跳过.
}
else
stringSave = "";//清空单词
}
if (charTemp == '\n') //如果回车,则列表加一行
{
rowCounter++;//行数加1
this.resultListBox1.Items.Add("————第 " + rowCounter + " 行————");
}
//回车,换行符,跳过,并且清空单词
if (charTemp == '\n' || charTemp == '\r' || charTemp == ' ')
stringSave = "";
i = i + 1;//计数器加1
if (i == getch.Length)//循环结束,打印相应信息
{
this.resultListBox1.Items.Add("————分析结束————");
}
}//end for
}//end else
}//end try
catch { }
}
//关闭文件
private void close_Click(object sender, EventArgs e)
{
this.Close();
}
}
}