词法分析实验目的与要求
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类;要求能对五类单词符号进行正确的分析,给出相应的提示信息。
实验内容
对于这个实验,我主要使用了三种函数:文件读取函数,逐行分析函数,以及数据打印函数。
实验步骤
首先规定好程序中合法的关键字、边界符、运算符、关系符、以及用户定义变量表,程序中所出现的常量记录表等。
在主函数中调用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);
}
}
}
}