实验二 算数表达式解释器的设计与实现
一. 实验目的
1、了解并掌握自顶向下语法分析的思想,熟悉递归下降子程序分析法。
2、了解并掌握语法制导翻译法,掌握采用递归子程序进行语义分析的方法。
二. 实验内容
用适当的程序设计语言编制一个算术表达式的解释器,并完成相应的调试,要求该程序能够读入一个算术表达式,运行后给出计算的结果。 1.算术表达式的解释过程(参考)
第一步:首先进行词法分析(即使用实验一编制的词法分析器),提取最终得到的结果——单词符号序列,将其作为语法和语义分析的输入;
第二步:调用算术表达式的语法分析器。本次实验要求采用递归下降子程序法编写语法分析器,并且此语法分析器中包含对语义的分析。
分析结束后,显示表达式的计算结果。 2.使用的文法
E –> TE’
E’ –> +TE’ |?|-TE’ T –> FT’
T’ –> *FT’|?|/TE’ F→i|(E) 其中i可为整数(简单点的),如果考虑周全的话,可取实数类型(需要看一下自己编制的词法分析器是否对实数进行了识别)。该文法的递归下降子程序参见课堂笔记(单纯语法分析部分在第四章介绍过, 结合语义分析的部分代码在第六章介绍过)。
3. 有能力的同学在完成加乘算术表达式的计算后,试扩充2 中定义的文法,增加识别减法和除法的规则,并修改对应的程序,使之能够识别并计算加减乘除四则运算式。
三. 实验要求
1. 程序完成后,由实验老师检查代码,验证程序的功能。如: 输入 (2+3)*10
对文法进行扩充的,输入 (12-8)*20/5+4 等等。
2. 实验二共4学时,实验完成后,提交一份实验报告,写清实验的目的、内容、思路、设计及实现的过程(包括关键的代码,不宜多),以及实验的结果。实验类型为设计型实验。
四. 程序设计流程图
语法分析器遵循自上而下语法分析的基本算法。其核心思想是将每个非终结符组织成函数的形式,并在每个函数中依据相应的产生式右部的符号序列,对读进的符号串进行匹配。如果在产生式右部遇到终结符,那么新读进的符号必须与该终结符一致;如果遇到非终结符,那么则根据预测分析表,调用相应的非终结符对应的函数继续匹配。如果不能满足以上两点,
1
则认为源程序出现了语法错误。算法的流程图如下所示:
开始 打开文件 Y 读取字符 关闭文件 读一个符号 N M1=0 { Y I++ M1=i N M2=0 、 Y j++ M2=j N } M3=0 Y k++ M3=k N i、j、k值是否相邻 语法分析错误 N 读下一个字符 输出运算结果 结束 2
五. 实验步骤
1、定义一些全局变量和数组,其中数组用来存放词法分析的结果,定义布尔型变量 flag用来作为错误信息的提示标志。关键代码如下: string[,] str = new string[50,2];
2、 打开词法分析的结果:点击词法分析按钮,将保存在磁盘上的词法分析结果赋值给 textbox并将其显示在文本框中。
3、进行语法分析:在进行语法分析前,首先将textbox中的字符串进行分割,调用 tiQuZiFu()方法,在该方法中我们首先定义三个数组m1,m2,m3分别记录左括号、右括号和顿号的位置,如果遇到左括号(譬如“((、()“)则继续向下读取下一个,如果下一个还为左括号则记录上一个左括号的位置,如若下一个不为左括号则记录上一个左括号的位置并将此时的位置变量i进行减1进行变量值的恢复。如果遇到顿号,记录当前的位置于m3中,此时继续往下走,如果下一个字符为左括号或者右括号,此时什么也不做。否则的话将i值减1进行位置的恢复。遇到右括号的情况与左括号的情况相似。最后调用Substring方法进行字符串的截取。关键代码如下:
for (int i = 0; i < m1.Count; i++) //进行字符串的截取 {
str[i, 0] = str1.Substring(Convert.ToInt32(m1[i]) + 1, Convert.ToInt32(m2[i]) - Convert.ToInt32(m1[i]) - 1);
str[i, 1] = str1.Substring(Convert.ToInt32(m2[i]) + 1, Convert.ToInt32(m3[i]) - Convert.ToInt32(m2[i]) - 1) }
4、判断括号是否合法,调用checkSpace()方法。由于定义了静态的数组str来存放词法分析的结果,我们先定义全局变量m来存放数组的真实长度。在该方法中首先判断左右括号的个数是否匹配,接着判断左右括号是否匹配.判断左右括号是否匹配的主要思想是:若存放括号的arr数组的第一个字符是右括号,则提示括号不匹配的错误;如果第一个为左括号,则继续往下找,直到找到右括号为止,此时将这两个字符从数组中移除。接下来从头开始遍历数组,直到找到错误或者将数组遍历完为止。关键代码如下: if (a != b) //左右括号不相等时 {
MessageBox.Show(\表达式不正确!!!\flag = false; } else {
for (int j = 0; j < arr.Count;) {
if (arr[0].Equals(\数组的头部为“)”时 提示出错 {
MessageBox.Show(\表达式不正确!!!\flag = false; break; }
3