(编译原理)实现词法分析器

实验内容

从磁盘中读取一个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();
        }
    }
}

实验结果

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值