利用SLR实现可编程计算器(表达式求值)
2012-11-20 14:40
344 查看
有些计算器,只能进行单步计算,就是说只能输入数字和加减乘除四则运算符号,而不能有括号的出现。可编程计算器就是指能输入括号、数字和四则运算符号,并对所输入的四则运算表达式进行分析,得最终计算出结果的计算器。
不多说下面用编译原理里面讲过的SLR文法来实现。
其实还有一种比较简单的方法——用栈来实现,可以看这里:http://blog.csdn.net/he_qiao_2010/article/details/8710495。
可编程计算器的SLR文法实现(表达式求值)
0. 在计算机科学中,文法是编译原理的基础,是描述一门程序设计语言和实现其编译器的方法。它可以使语言中的每个句子都能用严格定义的规则来构造。说白了类似于语文里面遣词造句的一种规则。比如一个句子的一般形式就是主、谓、宾,即:句子——>主谓宾。那么要构造一个句子,就只需要主语、谓语、宾语按照这个顺序排列就够了。在我们想设计的这个可编程计算器中数字就是0-9这十个数字,即:num——>[0-9]+。(这里+表示某个集合中的元素可以重复出现多次,但至少出现一次)这个实际上是正则表达式,也是文法的一类。
1. 在讲什么是SLR之前先说一下LR在编译技术里面的概念。LR(k)是指一种高效的、自下而上的针对于上下文无关的文法分析技术,其中L是指从左向右扫描输入,R是指构造最右推导的逆,而k是指决定分析动作时向前找的符号的个数。而SLR是LR方法中最简单的一种。(由于四则运算式比较简单,SLR已经足以描述所有的表达式)
2. 下面给出一个比较直观的例子,看一个文法如何分析一个四则运算表达式。
3. 首先给出这个文法:
(1) E_ -> E
(2) E -> E+T | E-T | T
(3) T -> T*F | T/F | F
(4) F -> ( E ) | id
也就等价于:
(1) E_ -> E
(2) E -> E+T
(3) E -> E-T
(4) E -> T
(5) T -> T*F
(6) T -> T/F
(7) T -> F
(8) F -> ( E )
(9) F -> id
用以上文法构建SLR分析表:
实际上整个构造过程要通过转换图来实现,而且画图过程比较繁琐,下面是通过转换图得到的便于程序实现的转移表。
负数表示按照第几个文法表达式进行规约。一些细节看源码。
实际上它的主要思想就是把整个表达式塞进栈里面,然后通过查表来决定是压栈还是出栈。整个过程,就是弹栈然后计算,又把计算结果压栈,再弹栈。。。等等。
而什么时候该出栈什么时候该入栈,由文法产生的转移表决定,这就也许是文法的神奇之处吧。我是感觉编译原理比较难学,一个First集和Follow集就纠结了半天。
好吧,下面看看程序的实现结果,下面有几张简单的截图(用MFC实现),如此界面,请大家不喜勿喷。。。^_^
生成词法单元(二元组)
分析表达式合法性,如果合法计算出结果
如果输入不合法的表达式
显示错误信息:
源码下载地址:http://www.pudn.com/downloads493/sourcecode/windows/other/detail2055486.html
2015-03-21更新源码的下载地址:
百度网盘:http://pan.baidu.com/s/1jG69m5o
不多说下面用编译原理里面讲过的SLR文法来实现。
其实还有一种比较简单的方法——用栈来实现,可以看这里:http://blog.csdn.net/he_qiao_2010/article/details/8710495。
可编程计算器的SLR文法实现(表达式求值)
0. 在计算机科学中,文法是编译原理的基础,是描述一门程序设计语言和实现其编译器的方法。它可以使语言中的每个句子都能用严格定义的规则来构造。说白了类似于语文里面遣词造句的一种规则。比如一个句子的一般形式就是主、谓、宾,即:句子——>主谓宾。那么要构造一个句子,就只需要主语、谓语、宾语按照这个顺序排列就够了。在我们想设计的这个可编程计算器中数字就是0-9这十个数字,即:num——>[0-9]+。(这里+表示某个集合中的元素可以重复出现多次,但至少出现一次)这个实际上是正则表达式,也是文法的一类。
1. 在讲什么是SLR之前先说一下LR在编译技术里面的概念。LR(k)是指一种高效的、自下而上的针对于上下文无关的文法分析技术,其中L是指从左向右扫描输入,R是指构造最右推导的逆,而k是指决定分析动作时向前找的符号的个数。而SLR是LR方法中最简单的一种。(由于四则运算式比较简单,SLR已经足以描述所有的表达式)
2. 下面给出一个比较直观的例子,看一个文法如何分析一个四则运算表达式。
3. 首先给出这个文法:
(1) E_ -> E
(2) E -> E+T | E-T | T
(3) T -> T*F | T/F | F
(4) F -> ( E ) | id
也就等价于:
(1) E_ -> E
(2) E -> E+T
(3) E -> E-T
(4) E -> T
(5) T -> T*F
(6) T -> T/F
(7) T -> F
(8) F -> ( E )
(9) F -> id
用以上文法构建SLR分析表:
标识符 | + | - | * | / | ( | ) | $ | id | E | T | F | acc | |
值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 17 | |
#defineSTAT 16 #defineACTION 8 #defineTURN 3 /************转移表(动作部分)***************/ int MOVETABLE[STAT][ACTION] = { { 0, 0, 0, 0, 4, 0, 0,5}, /*0*/ { 6, 7, 0, 0, 0,-1,17, 0}, /*1*/ {-4,-4,10,11, 0,-4,-4, 0}, /*2*/ {-7,-7,-7,-7, 0,-7,-7, 0}, /*3*/ { 0, 0, 0, 0, 4, 0, 0, 5},/*4*/ {-9,-9,-9,-9, 0,-9,-9, 0},/*5*/ { 0, 0, 0, 0, 4, 0, 0, 5}, /*6*/ { 0, 0, 0, 0, 4, 0, 0, 5}, /*7*/ {-2,-2,10,11, 0,-2,-2, 0}, /*8*/ {-3,-3,10,11, 0,-3,-3, 0},/*9*/ { 0, 0, 0, 0, 4, 0, 0, 5},/*10*/ { 0, 0, 0, 0, 4, 0, 0, 5}, /*11*/ {-5,-5,-5,-5, 0,-5,-5, 0}, /*12*/ {-6,-6,-6,-6, 0,-6,-6, 0}, /*13*/ { 6, 7, 0, 0, 0,15, 0, 0},/*14*/ {-8,-8,-8,-8, 0,-8,-8, 0}/*15*/ }; /************转移表(转移部分)***************/ int TURNTABLE[STAT][TURN] = { { 1, 2, 3 }, /*0*/ { 0, 0, 0 }, /*1*/ { 0, 0, 0 }, /*2*/ { 0, 0, 0 }, /*3*/ {14, 2, 3 }, /*4*/ { 0, 0, 0 }, /*5*/ { 0, 8, 3 }, /*6*/ { 0, 9, 3 }, /*7*/ { 0, 0, 0 }, /*8*/ { 0, 0, 0 }, /*9*/ { 0, 0, 12}, /*10*/ { 0, 0, 13}, /*11*/ { 0, 0, 0 }, /*12*/ { 0, 0, 0 }, /*13*/ { 0, 0, 0 }, /*14*/ { 0, 0, 0 } /*15*/ };
负数表示按照第几个文法表达式进行规约。一些细节看源码。
实际上它的主要思想就是把整个表达式塞进栈里面,然后通过查表来决定是压栈还是出栈。整个过程,就是弹栈然后计算,又把计算结果压栈,再弹栈。。。等等。
而什么时候该出栈什么时候该入栈,由文法产生的转移表决定,这就也许是文法的神奇之处吧。我是感觉编译原理比较难学,一个First集和Follow集就纠结了半天。
好吧,下面看看程序的实现结果,下面有几张简单的截图(用MFC实现),如此界面,请大家不喜勿喷。。。^_^
生成词法单元(二元组)
分析表达式合法性,如果合法计算出结果
如果输入不合法的表达式
显示错误信息:
源码下载地址:http://www.pudn.com/downloads493/sourcecode/windows/other/detail2055486.html
2015-03-21更新源码的下载地址:
百度网盘:http://pan.baidu.com/s/1jG69m5o
相关文章推荐
- 表达式求值(利用栈编程实现)
- 利用栈实现的后缀形式的算术表达式的求值的c++程序
- 利用 Lambda 表达式实现 Java 中的惰性求值
- 利用 Lambda 表达式实现 Java 中的惰性求值
- 利用堆栈实现表达式求值
- 利用栈实现算术表达式求值(Java语言描述)
- 利用栈实现算术表达式求值(Java语言描述)
- 利用栈实现算术表达式的求值
- 利用栈实现算术表达式求值(Java语言描述)
- 利用栈实现算术表达式求值(Java语言描述)
- C++利用链栈实现表达式求值
- 利用正则表达式实现关键词标红
- C#利用正则表达式实现字符串搜索
- EasyUI 之 DataGrid利用用拉姆达表达式实现分页查询
- 简单表达式求值(用栈实现)
- js利用运算符优先级实现if else条件判断表达式
- 用二叉树实现表达式中缀式变后缀式并求值
- c语言栈实现表达式求值
- 利用二叉树实现表达式计算
- 算术表达式求值(中缀转后缀,后缀求值,java 栈实现)