词法分析程序
这个学期终于开设闻名已久的编译原理课程,目睹了天书的奥秘。发现编译原理的确比数据结构难多了,不过能掌握一些编译原理的知识,对我们做程序的是非常有用的!
PASCAL语言子集的语法定义
〈PASCAL子集程序〉→〈变量说明〉〈分程序〉。
〈变量说明〉→〈空〉|VAR〈变量表〉:INTEGER;
〈变量表〉→〈变量〉|〈变量〉,〈变量表〉
〈变量〉→〈标识符〉
〈分程序〉→BEGIN〈语句组〉END
〈语句组〉→〈语句〉|〈语句〉;〈语句组〉
〈语句〉→〈赋值语句〉|〈条件语句〉|〈WHILE语句〉|〈分程序〉
〈赋值语句〉→〈变量〉:=〈算术表达式〉
〈条件语句〉→IF〈布尔表达式〉THEN〈语句〉ELSE〈语句〉
〈WHILE语句〉→WHILE〈布尔表达式〉DO〈语句〉
〈算术表达式〉→〈项〉|〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉
〈项〉→〈初等量〉|〈项〉*〈初等量〉|〈项〉/〈初等量〉
〈初等量〉→〈无符号数〉|〈变量〉|(〈算术表达式〉)
〈关系表达式〉→〈算术表达式〉〈关系运算符〉〈算术表达式〉
〈标识符〉→〈字母〉|〈标识符〉〈字母〉|〈标识符〉〈数字〉
〈无符号数〉→〈数字〉|〈无符号数〉〈数字〉
〈关系运算符〉→〈|〈= | =| 〉=| 〉|〈〉
〈字母〉→ A│B│C│D│E│F│G│H│I│J│K│L│M│N│O│P│Q│R│S│T│
│U│V│W│X│Y│Z
〈数字〉→ 1│2│3│4│5│6│7│8│9│0
本节进行词法分析程序的编程与调试。
目的与要求
1)目的
通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
2)要求
⑴ 掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。
⑵ 掌握词法分析的实现方法。
⑶ 上机调试编出的词法分析程序。
这里我就不给出测试的程序代码啦!大家可以自己构造符合Pascal语言文法的程序代码。下面我主要介绍这个词法分析程序的代码如何编写。
开发环境:Visual Studio 2008 (C#)
主窗体(FrmMain)代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CompilerApp
{
public partial class FrmMain : Form
{
//定义关键字数组
string[] Keywords = { "BEGIN","DO","ELSE","END","INTEGER",
"IF","THEN","VAR","WHILE"};
//定义运算符数组
string[] Operations = { "+", "-", "*", "/", "<", "<=", ">=", ">", "=", "<>", ":=" };
//定义分隔符数组
string[] Paritions = { ",", ":", ";", ".", "(", ")" };
char ch;
int i = -1;
char[] CodeStr = null;
public FrmMain()
{
InitializeComponent();
}
private void btnRead_Clicked(object sender, EventArgs e)
{
OpenFileDialog openDlg = null;
try
{
openDlg = new OpenFileDialog();
openDlg.Filter = "文本文件|*.txt|所有文件|*.*";
if (openDlg.ShowDialog() == DialogResult.OK)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(openDlg.FileName, System.Text.Encoding.GetEncoding("GB2312")))
{
this.txtSourceCode.Text = sr.ReadToEnd();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
finally
{ openDlg = null; }
}
/// <summary>
/// 获取下一个字符
/// </summary>
private void getNextChar()
{
this.i += 1;
if (this.i < this.CodeStr.Length)
this.ch = this.CodeStr[this.i];
}
/// <summary>
/// 获取前一个字符
/// </summary>
private void getPreviewChar()
{
this.i -= 1;
this.ch = this.CodeStr[i];
}
/// <summary>
/// 判断是否是关键字
/// </summary>
/// <param name="s">待比较的字符串</param>
/// <returns>是关键字返回true,否则返回false</returns>
private bool isKeyWord(string s)
{
foreach (string keyWord in this.Keywords)
{
if (keyWord.Equals(s) == true)
return true;
}
return false;
}
/// <summary>
/// 判断是否是运算符
/// </summary>
/// <param name="s">待比较的字符串</param>
/// <returns>是运算符返回true,否则返回false</returns>
private bool isOperation(string s)
{
foreach (string Operation in this.Operations)
{
if (Operation.Equals(s) == true)
return true;
}
return false;
}
/// <summary>
/// 判断是否是分隔符
/// </summary>
/// <param name="s">待比较的字符串</param>
/// <returns>是分隔符返回true,否则返回false</returns>
private bool isParition(string s)
{
foreach (string Parition in this.Paritions)
{
if (Parition.Equals(s) == true)
return true;
}
return false;
}
/// <summary>
/// 词法分析方法
/// </summary>
private void LexAnalysis()
{
string _ElementStr = string.Empty;
int len = this.CodeStr.Length;
this.getNextChar();
try
{
while (this.i < len)
{
_ElementStr = string.Empty;
if (Char.IsLetter(this.ch) == true)
{
//字母
while (Char.IsLetter(this.ch) == true && this.i < len)
{
_ElementStr += this.ch;
this.getNextChar();
}
if (this.isKeyWord(_ElementStr) == true)
this.txtInfo.AppendText(string.Format("(1,{0})\n", _ElementStr));
else
this.txtInfo.AppendText(string.Format("(2,{0})\n", _ElementStr));
continue;
}
else if (Char.IsDigit(this.ch) == true)
{
//常量
while (Char.IsDigit(this.ch) == true && this.i < len)
{
_ElementStr += this.ch;
this.getNextChar();
}
this.txtInfo.AppendText(string.Format("(5,{0})\n", _ElementStr));
continue;
}
else if (this.isOperation(this.ch.ToString()) == true)
{
//运算符
_ElementStr = this.ch.ToString();
this.getNextChar();
if (_ElementStr.Equals("<") && this.ch.Equals('=') == true)
this.txtInfo.AppendText(string.Format("(3,{0})\n", _ElementStr + this.ch.ToString()));
else if (_ElementStr.Equals(">") && this.ch.Equals('=') == true)
this.txtInfo.AppendText(string.Format("(3,{0})\n", _ElementStr + this.ch.ToString()));
else if (_ElementStr.Equals("<") && this.ch.Equals('>') == true)
this.txtInfo.AppendText(string.Format("(3,{0})\n", _ElementStr + this.ch.ToString()));
else
this.txtInfo.AppendText(string.Format("(3,{0})\n", _ElementStr));
}
else if (this.isParition(this.ch.ToString()) == true)
{
//分隔符
_ElementStr = this.ch.ToString();
this.getNextChar();
if (_ElementStr.Equals(":") && this.ch.Equals('=') == true)
this.txtInfo.AppendText(string.Format("(4,{0})\n", _ElementStr + this.ch.ToString()));
else
{
this.getPreviewChar();
this.txtInfo.AppendText(string.Format("(4,{0})\n", this.ch.ToString()));
}
}
else
{
}
this.getNextChar();
}
}
catch (Exception ex)
{
Console.WriteLine("{0}\n{1}", ex.Message, this.i.ToString());
}
}
private void btnLexAnalysis_Click(object sender, EventArgs e)
{
this.txtInfo.Text = string.Empty; //清空输出信息
i = -1;
this.CodeStr = this.txtSourceCode.Text.ToCharArray(); //获取源代码字符数组
this.LexAnalysis();
}
}
}
源程序:编译器(词法分析)



浙公网安备 33010602011771号