编译原理——词法分析程序(C#)

词法分析实验目的与要求

  编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类;要求能对五类单词符号进行正确的分析,给出相应的提示信息。

实验内容

  对于这个实验,我主要使用了三种函数:文件读取函数,逐行分析函数,以及数据打印函数。

实验步骤

  首先规定好程序中合法的关键字、边界符、运算符、关系符、以及用户定义变量表,程序中所出现的常量记录表等。

  在主函数中调用GetWord(filename)方法分析程序文件,调用Display系列函数打印内容。
在这里插入图片描述
在这里插入图片描述

test.txt

int a=5;
for(int i=0;i<10;i++)
{
	if(i>=5)
	{
		i=i+1;
		continue;
	}
	else if(i==a)
	{
		i=a;
	}
	else
	{
		i=i*2;
	}
}

Program.cs

using System;
using System.Collections.Generic;
using System.IO;
namespace Lexer
{
    class Program
    {
        static List<char> borders = new List<char>() {',',';','{','}','(',')'};
        static List<string> keys = new List<string>() { "int", "if", "else", "for", "while", "do", "return", "break", "continue" };
        static List<string> arithmetics = new List<string>() { "+", "-", "*", "/","++"};
        static List<string> relations = new List<string>() { "<", "<=", "=", "==", ">", ">=","!=" };
        static List<string> consts = new List<string>();
        static List<string> labels = new List<string>();
        static void Main(string[] args)
        {
            string fileName = "test.txt";
            GetWords(fileName);
            DisplayLabel();
            DisplayConsts();
            Console.ReadKey();
        }
        /// <summary>
        /// 打开一个程序文件,逐行分析
        /// </summary>
        /// <param name="fileName"></param>
        static void GetWords(string fileName)
        {
            using(Stream stream = File.OpenRead(fileName))
            {
                StreamReader reader = new StreamReader(stream);
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine();
                    Analysis(line);
                }
            }            
        }
        /// <summary>
        /// 分析每行代码
        /// </summary>
        /// <param name="line"></param>
        static void Analysis(string line)
        {
            char[] chars = line.ToCharArray();//将每行字符串看作是字符数组
            List<char> word = new List<char>();//临时保存分解出来的变量,关键字,边界符等,可将其转化成string,用于打印
            for (int i = 0; i < chars.Length;)
            {
                char ch = chars[i];
                while (ch <= 32 && ch > 0)//跳过不可见字符
                {
                    if (i < chars.Length - 1)
                    {
                        ch = chars[++i];
                    }
                    else
                    {
                        break;
                    }
                }
                if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')//若以字母开头,判断是关键字还是变量
                {
                    while (true)
                    {
                        word.Add(ch);// 保存当前分析出来的变量、关键字、边界符等,可将其转化成string,用于打印
                        if (i < chars.Length - 1)//是否到达字符数组末尾时
                        {
                            ch = chars[++i];                            
                        }
                        else
                        {
                            string Word = new string(word.ToArray());
                            //判断是关键字还是变量
                            if (keys.Contains(Word))
                            {
                                Console.WriteLine($"{Word}    关键字");
                            }
                            else
                            {
                                if (!labels.Contains(Word))
                                {
                                    labels.Add(Word);
                                }
                                Console.WriteLine($"{Word}    变量");
                            }                          
                            word.Clear();
                            i++;
                            break;
                        }
                        if (!(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9'))//当出现非字母或数字的字符,即到达变量或关键字的结尾
                        {
                            string Word = new string(word.ToArray());
                            if (keys.Contains(Word))//判断是关键字还是变量
                            {
                                Console.WriteLine($"{Word}    关键字");
                            }
                            else
                            {
                                if (!labels.Contains(Word))
                                {
                                    labels.Add(Word);
                                }
                                Console.WriteLine($"{Word}    变量");
                            }
                            word.Clear();
                            break;
                        }
                    }
                }
                else if(ch >= '0' && ch <= '9')//遇到数字时
                {
                    while (true)
                    {
                        word.Add(ch);
                        ch = chars[++i];
                        if (!(ch >= '0' && ch <= '9'))//直到数字结束
                        {
                            string Word = new string(word.ToArray());
                            if (!consts.Contains(Word))
                            {
                                consts.Add(Word);
                            }
                            Console.WriteLine($"{Word}    常量");
                            word.Clear();
                            break;
                        }
                    }
                }                         
                else if (ch == '+' || ch == '-' || ch == '*' || ch == '/')//遇到运算符
                {
                    string Word;
                    word.Add(ch);
                    ch = chars[++i];
                    if (chars[i-1]=='-'&&ch >= '0' && ch <= '9')//是负数还是 '-' 运算符
                    {
                        while (true)
                        {
                            word.Add(ch);
                            ch = chars[++i];
                            if (!(ch >= '0' && ch <= '9'))
                            {
                                Word = new string(word.ToArray());
                                if (!consts.Contains(Word))
                                {
                                    consts.Add(Word);                                  
                                }
                                Console.WriteLine($"{Word}    常量");
                                word.Clear();
                                break;
                            }
                        }
                    }
                    else if(ch == '+' || ch == '-' || ch == '*' || ch == '/')//判断是否是“++”,“--”等运算符
                    {
                        word.Add(ch);
                        ch = chars[++i];
                    }
                    Word = new string(word.ToArray());
                    word.Clear();
                    if (arithmetics.Contains(Word))//编程语言是否包含此运算符
                    {
                        Console.WriteLine($"{Word}    运算符");
                    }
                }
                else if(ch == '>' || ch == '<' || ch == '=' || ch == '!')//判断是否是关系运算符
                {
                    word.Add(ch);
                    ch = chars[++i];
                    if (ch == '=')
                    {
                        word.Add(ch);
                        ch = chars[++i];
                    }
                    string Word = new string(word.ToArray());
                    word.Clear();
                    if (relations.Contains(Word))
                    {
                        Console.WriteLine($"{Word}    关系符");
                    }
                }
                else if(borders.Contains(ch))//是否是边界符
                {
                    word.Add(ch);
                    if (i < chars.Length - 1)
                    {
                        ch = chars[++i];
                    }
                    else
                    {
                        i++;
                    }
                    string Word = new string(word.ToArray());
                    word.Clear();
                    Console.WriteLine($"{Word}    边界符");
                }
                else
                {
                    i++;
                }
            }
        }
        /// <summary>
        /// 打印变量表
        /// </summary>
        static void DisplayLabel()
        {
            Console.WriteLine("-------------------------------------");
            Console.WriteLine("变量:");
            foreach(string label in labels)
            {
                Console.WriteLine(label);
            }
        }
        /// <summary>
        /// 打印程序中出现的常数
        /// </summary>
        static void DisplayConsts()
        {
            Console.WriteLine("-------------------------------------");
            Console.WriteLine("常数:");
            foreach (string c in consts)
            {
                Console.WriteLine(c);
            }
        }

    }
}

猜你喜欢

转载自blog.csdn.net/qq_40404477/article/details/100856667