编译原理计算器calculator+文法分析

我们的编译原理作业

老师让写一个calculator,第一次写编译程序可能里面有不少冗余和低级处理,但是也push出来和大家共勉。

环境

我使用的是VS2019,用的c语言来做的。

目标

计算器接受四则运算表达式为输入(如下所示)。如果表达式语法正确,则输出计算结果,否则报错,指出错误位置及原因。

Input 1:
float a; 
int b; 
a = (10.44*356+1.28) / 2 + 1024 * 1.6;
b = a * 2 – a/2;
write(b);
write(a).
Output 1:
   5246
   3497.36
Input 2:
float a; 
int b; 
a = (10.44*356+1.28) / 2 + 1024 * 1.6;
b = a * 2 – c/2;
write(b).
Output 2:
   Error(line 4): undefined identifier . 

1)支持浮点数和整数两种类型,浮点数可以转换成整数;整数不可以转换成浮点数;
2)每个语句需要以“;”结束,以“.”表示全部输入的结束
3)变量需要先声明再使用;
4)变量名可以是由数字和字母组成,但首字符必须是字母。
5)每个表达式中使用的变量需要在之前已经有赋值。
6)输出语句使用write(a),输出并换行,其中a为int类型或者float类型的变量名。

我的编程思路

首先scan函数和cal函数最为关键,也最能体现我的主体思想。
定义了变量的struct结构体,建立了变量的双链表用于存储和查找变量,cal函数返回的就是变量链表的头部指针。
当然还有查找变量、增加变量的函数等。都是对于这个双链表的操作。
对变量的定义,我使用了IDENTIFIER_F 和 IDENTIFIER_I 分别表示我scan到了的token是标识符。
然后当我发现这是一个使用标识符的定义语句时,在case IDENDTIFIER_X 中检查下一个token ,如果是= 就是进入赋值操作,
对变量链表进行相应修改。
而对于赋值语句,我添加枚举类型VAL ,当我检查到token是变量的时候,进入case VAL:,为了区分这个变量是在运算中,
还是一个类似a=b+1 的赋值语句我就在检查下一个token是不是=。(那这个时候可能会有疑问,怎么区分float a=1;和a=1;其实
第一种情况由于已经检测到了标识符所以不会进入case VAL;在case IDENTIFITER_F就会完成创建变量的操作)如果发现下一个,
token是=,就将赋值标识符设置为1,只用当is_giveValue=1的时候才会进入到cal中的计算后缀表达式的部分。而如果token不是=,
那么就说明这个变量是在计算表达式中的,代表一个数值,我就在双链表中寻找这个变量名,如果没找到报错,找到的话就创建一
个Token结构,并将其push进post堆栈,直接完成变量到数值的转换。

注:对于报错则使用了fget按行读取以及全局变量LINE和记录当前line内容的全局BUF。

我的文法定义

program 程序
statement 声明
identifier 类型定义
value 变量
Assignment statement 赋值语句
Normal statement 一般语句
Computation statement 计算语句
Function statement 功能语句
Write statement 输出语句
num 数字常量
digital_I 整数
digital_F 浮点数
Reserved word 保留字
calulation define{  (对计算器计算语句的定义 level代表优先级,数字越大意味着优先级越高)
	level_1 代表加减
	level_2 代表乘除
	level_3 代表负号
	
	level_4 数字或括号
}

相关正则定义:

Letter [a-z,A-Z] 
Digital [0-9]
Underline ['_']
specific_num {Digital}((.{Digital}+)|{Digital}*)

	<program> -> <statement> | <statement> (<Normal statement> | Ø | Function statement) <program> 
	
	<statement> -> <identifier> <value> | <identifier> <Assignment statement>
	
	<Normal statement> -> <value> <'='> <Computation statement>
	
	<Computation statement> -> <level_1>
	
	<level_1> -> <level_1> <'+'> <level_2> | <level_1> <'-'> <level_2> | <level_2>
	
	<level_2> -> <level_2> <'*'> <level_3> | <level_2> <'/'> <level_3> | <level_3>
	
	<level_3> -> <'-'><level_4> | <level_4>
	
	<level_4> -> <'('> <level_1> <')'> | <num>
	
	<Function statement> -> <Write statement> | <Other statement>  /*(目前其他功能语句为空) */
	
	<Write statement> -> <Reserved word> <'('> <value> <')'>
	
	<Reserved word> -> <'write'>
	
	<Assignment statement> -> <value> <'='> <num>
	
	<value> -> (Letter)(Letter)*(Digital)*Underline*(Digital)*(Letter)*Underline*(Digital)*(Letter)*
	
	<num> -> <digital_F> | <digital_I>

源代码

我已经上传到了gitee
点击查看源代码

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<!DOCTYPE html> <html> <head> <title>计算器</title> <style> #calculator { width: 300px; height: 400px; margin: 0 auto; background-color: #eee; border: 1px solid #999; padding: 20px; } #screen { width: 100%; height: 60px; background-color: #fff; border: 1px solid #999; margin-bottom: 10px; font-size: 30px; text-align: right; padding: 10px; } .button { width: 60px; height: 60px; background-color: #fff; border: 1px solid #999; margin-right: 10px; margin-bottom: 10px; font-size: 30px; text-align: center; line-height: 60px; float: left; cursor: pointer; } .clear { background-color: #f00; color: #fff; } .equals { background-color: #0f0; color: #fff; } </style> </head> <body> <div id="calculator"> <div id="screen"></div> <div class="button" id="clear">C</div> <div class="button" id="divide">/</div> <div class="button" id="multiply">*</div> <div class="button" id="subtract">-</div> <div class="button" id="seven">7</div> <div class="button" id="eight">8</div> <div class="button" id="nine">9</div> <div class="button" id="add">+</div> <div class="button" id="four">4</div> <div class="button" id="five">5</div> <div class="button" id="six">6</div> <div class="button" id="one">1</div> <div class="button" id="two">2</div> <div class="button" id="three">3</div> <div class="button" id="zero">0</div> <div class="button" id="decimal">.</div> <div class="button equals" id="equals">=</div> </div> <script> let screen = document.getElementById("screen"); let clear = document.getElementById("clear"); let divide = document.getElementById("divide"); let multiply = document.getElementById("multiply"); let subtract = document.getElementById("subtract"); let add = document.getElementById("add"); let equals = document.getElementById("equals"); let buttons = document.querySelectorAll(".button:not(#clear):not(#divide):not(#multiply):not(#subtract):not(#add):not(#equals)"); let expression = ""; clear.addEventListener("click", function(){ expression = ""; screen.innerHTML = ""; }); divide.addEventListener("click", function(){ expression += "/"; screen.innerHTML = expression; }); multiply.addEventListener("click", function(){ expression += "*"; screen.innerHTML = expression; }); subtract.addEventListener("click", function(){ expression += "-"; screen.innerHTML = expression; }); add.addEventListener("click", function(){ expression += "+"; screen.innerHTML = expression; }); equals.addEventListener("click", function(){ try { expression = eval(expression); } catch (err) { expression = "Error"; } screen.innerHTML = expression; expression = ""; }); for (let i = 0; i < buttons.length; i++) { buttons[i].addEventListener("click", function(){ expression += this.innerHTML; screen.innerHTML = expression; }); } </script> </body> </html>

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值