编译原理实验-带变量的中缀转后缀以及错误处理



先来实验指导书:


一、实验任务
设计、编制并调试一个中缀表达转换为后缀表达的实验程序,加深对词法分析、语法分析、语义分析及代码生成的理解。
二、 实验内容
1、词法
输入:扩展ASCII码字符集字符。除大小写26英文字母(letter)和数字0-9(digit)以及+  -  *  /  ^    =  ;  ,  (  )以外,所有其他字符一律按等同于空格处理,一般用来分隔单词。
输出:识别单词,单词包括关键字、运算符、界符、标识符和整型常数。
(1)关键字:var
(2)运算符和界符:+  -  *  /  ^    =  ;  ,  (  )
其中:乘除运算符(*, /)返回具有不同属性值的单词mulop,
加减运算符(+, -)返回具有不同属性值的单词addop。?
(3)标识符(id)和整型常数(num):
标识符(id)和整型常数(num)最大长度为8个字符,定义如下。
id = letter (letter | digit)* //以字母打头字母和数字组成的符号串
num = digit digit*//整形常数必须大于等于一位
2、语法(主要!!)
根据输入的单词序列,分析是否符合语法规则,如果不符合,应指明位置与理由;如果符合,则执行相应的语义子程序完成语义分析及中缀表达转换为后缀表达的过程。需注意的是,这里给出的是二义文法,从语义上考虑,表达式的计算按先幂次运算(^),再乘除运算(*, /)的  最后加减运算(+, - )的优先顺序; 括号((, ))用于调整运算先后顺序,既括号内部分先计算;赋值运算(=)最后进行。本实验系统的语法规则是:
program → compound
          复合功能
compound →  declaration  assignstatement  compound  |  ε
             定义            赋值
declaration →  var  identifier_list  ;  |  ε
    定义                 标识符
dentifier_list → id  ,  dentifier_list  |  id 
                     标识符中间可以有逗号相隔
assignstatement → id  =  expression  ;  |  ε
                         词句              必须有赋值号
expression → expression  addop  expression  |
加号两侧必须有单词
             expression  mulop  expression  |
乘号两侧必须有单词
             expression  ^  expression  |
幂两侧必须有单词
             (  expression  )  |
括号中间必须有单词
             id  |  num
3、语义分析及代码生成
语义分析的主要任务是判断变量是否先定义后使用(只有这一个)。代码生成的的主要任务是将赋值语句从中缀表达转换为后缀表达。
三、 实验示例
示例1:
输入:
var a,b;
a = 10;
b = 5;
var x;
x = a + ( 25 * b  ) ^ 2;
输出:
a  10  =
b  5  =
x  a  25  b  *  2  ^  +  =




示例2:
输入:
var a;
a = 10;
b = 5;
var x;
x = a + ( 25 * b ^ 2;
输出:
第3行错误: 变量b未定义。
第5行错误: 缺右括号。


这坨代码全程都是压力比较大的情况下敲完的,哎挺简单的实验被我敲了350多行,还是能力不足,应该想出更好的方法。首先用逆波兰解决掉中缀转后缀,然后就是错误处理了。他这里不满足所有语法的都算错误吧,分为词法语法和语义,前前后后共找出17种错误,后来比较麻烦转化成signal数组检错,处理这些错误画了好多时间,一百多行的代码变成300多行。。


这里我模拟的是解释程序,老师后来让改翻译程序,改了的有点难看,这里就贴出解释程序:

附测试数据:

6
5
var a,b;
a = 10;
b = 5;
var x;
x = a + ( 25 * b  ) ^ 2;
5
var a;
a = 10;
b = 5;
var x;
x = a + ( 25 * b ^ 2;
2
3 = 1 + 2;
3 = 1 & 2;
7
var apple666,banana,fffffffff,ff,0ccc,666p,1234;
banana = ( apple666 + 3 ) * 2;
ff = ( apple666 + 333333333 ) * 2;
banana = ( apple666 + 3 ) * 2
var a,b c d;
var banana;
9 + ( 3 - 1) * 3 + 10 / 2 = ;
13
var x;
x = 9 + ( 3 - 1) * 3 + 10 / 2;
x = 999999999 + 1;
x = 9 + ( 3 - 1) * + / 2;
x = 9 + ( 3 - 1) * - / 2;
x = 9 + ( 3 - 1) + * / 2;
x = 9 + ( 3 - 1) * 3 +  / ;
x = 9 + ( 3 - 1) * 3 +  ^ ;
x = 9 + ( - ) * 3 + 10 / 2;
x = 9 + ( ) * 3 + 10 / 2;
x = 9 + ( 3 - 1) * 3 + 10  2;
x = 9 + (((( 3 - 1 ) * 3 + 10 / 2;
x = 9 + ( 3 - 1 )))))) * 3 &

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在QT中,想要进行中缀表达式后缀表达式的操作,可以按照以下步骤进行: 1. 创建一个栈和一个输出队列,用于存放操作符和中间结果。 2. 从左到右扫描中缀表达式的每个字符。 3. 如果扫描到数字,直接将其加入到输出队列中。 4. 如果扫描到左括号,将其入栈。 5. 如果扫描到右括号,将栈中的操作符弹出并加入到输出队列,直到遇到左括号为止。 6. 如果扫描到其他运算符,先判断栈顶运算符的优先级: a. 如果栈为空或栈顶为左括号,则将该运算符入栈。 b. 如果栈顶运算符的优先级大于等于当前运算符的优先级,将栈顶运算符弹出并加入到输出队列,然后将当前运算符入栈。 c. 如果栈顶运算符的优先级小于当前运算符的优先级,将当前运算符入栈。 7. 扫描完中缀表达式后,将栈中剩余的运算符依次弹出并加入到输出队列。 根据提供的引用内容,您提到了括号的优先级要高于乘除法运算符,因此在QT中缀后缀的过程中,括号应该优先入栈。 总结起来,QT中缀后缀符号的步骤为: 1. 创建一个栈和一个输出队列。 2. 从左到右扫描中缀表达式的每个字符。 3. 根据扫描到的字符进行相应的操作:数字则加入输出队列,左括号则入栈,右括号则将栈中的运算符弹出并加入输出队列直到遇到左括号,其他运算符则根据优先级判断是否入栈或加入输出队列。 4. 扫描完中缀表达式后,将栈中剩余的运算符依次弹出并加入输出队列。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值