zoukankan      html  css  js  c++  java
  • 编译原理课程设计——语法分析器

    实验目的

      了解掌握算符优先分析的基本方法、内容;学会科学思考并解决问题,提高程序设计能力。

    实验内容与要求

      用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。

    文法表示  

        S -> v=E | E? | clear

        E -> E+T | E–T | T

        T -> T*F | T/F | F

        F -> (E) | v | c

    问题分析

      由于要求用算符优先分析方法来进行程序的语法分析,所以我们要根据给出的文法来设计优先关系表。对每个非终结符,求出:

        FIRSTVT(S) = { v , ? , clear }                 LASTVT(S) = { ? , clear }

        FIRSTVT(F) = { ( , v , c }                       LASTVT(F) = { ) , v , c }

        FIRSTVT(T) = {* , / , ( , v , c }               LASTVT(T) = {* , / , ) , v , c }

        FIRSTVT(E) = {+ , - , * , / , ( , v , c}       LASTVT(E) = {+ , - , * , / , } , v , c}

      符号的种别码如下表所示:

       

      优先关系表如下:

           

    先简要分析一下语法分析的大致流程:

             当有句子要进行处理时,首先要对其进行词法分析来分解出该句子中的每个符号,然后将该句子按照算符优先算法压入归约栈中,如果可以顺利归约,则说明这是一个合法的句子,否则该句子非法。

             这里有一个需要考虑的地方,就是如何进行归约。由于文法已经给定,所以我们考虑设计一个文法表,文法表中的内容就是可归约串的种别码的顺序,比如v=E可以表示为9,1,13。这样的话当我们要进行一次归约时,只用按顺序存储最左素短语中符号的种别码,然后拿这个种别码序列与文法表进行匹配,就可知道当前归约需要执行哪些操作。

             还有一点需要注意,就是如何对一个表达式进行求值。这里需要我们设计一个二元组的变量名表,这个变量名表可以根据变量的名称来返回变量的数据。变量名表的具体设计见详细设计部分。

             由于是简化分析,所以这个程序只考虑整数的处理。

             有了上面的分析,可以构造出算符优先分析算法的流程图,如下图所示。   

    详细设计

    (1)词法分析部分

      由于词法分析的内容在课程设计1中已经介绍,并且这次的状态转换图与课程设计1中的非常相似,所以这里就不过多介绍。

    (2)优先关系表

      在程序中我们用一个二维数组priTable[][]来存储算符间的优先关系。priTable[a][b]=1表示a>b; 。priTable[a][b]=0表示a=b; 。priTable[a][b]=-1表示a<b;

    (3)归约栈的设计

      由于真正要设计一个栈来处理问题有些麻烦,所以这里可以用一个数组s[]来代替栈,如图2.1所示,i就代表栈顶指针,s[i]就代表栈顶的元素。归约栈中的结点,构造一个数据结构Node来表示,Node中有三个元素,算符的单词名str、算符的种别码type、算符的数值num。当我们词法分析来扫描出一个单词的时候,就可以填充Node结点的单词名、种别码和数值。

    (4)归约过程

      在问题分析中我们介绍到用文法表来进行归约,文法表graTable是一个二维数组,保存文法中算符的种别码。归约的时候,只要最左素短语的种别码匹配到文法表中的某一项,就可以按照那个归约操作来进行归约。归约的步骤参照流程图中的操作,设置栈顶指针,将栈顶结点的种别码设为非终结符,并且还要保存这一次归约产生的结果。举个例子,比如E->E+T 这次归约,E+T会产生一个结果,这个结果最终就保存在栈顶结点的数值域中。需要注意的是,Node结点中数值域的主要作用就是在归约中保存结果。

    (5)变量名表

      变量名表varTable的作用是根据变量名来返回该变量的数值,是一个二元组的序列,为了方便这里采用STL模板中的map来实现。变量名表的主要用处也就是在赋值语句和表达式求值当中,比如说当有赋值语句a=5需要归约时,检查变量a是否存在于变量名表中,如果不存在就将a和5添加至变量名表,如果a存在那么就可以更新变量名表中a的数值。并且在有F->v这样的归约中,如果查找到v不在变量名表中,说明v就是一个未赋值的变量,这样就产生异常。

    输入与输出

      程序的输出有:判断语法是否正确;输出表达式求值的结果;输出错误信息。

    样例输入(输入来自文件in.txt):

      a = 5

      b = a + 10

      b?

      b + a * a?

      a = (a + b) * (b - a) + 5 + 4 / 2

      a?

      clear

      ab =

    样例输出(输出至文件out.txt):

      a = 5 为合法句子,执行成功

      b = a + 10 为合法句子,执行成功

      b? 为合法句子,执行成功

      b 的值为 15

      b + a * a? 为合法句子,执行成功

      b + a * a 的值为 40

      a = (a + b) * (b - a) + 5 + 4 / 2 为合法句子,执行成功

      a? 为合法句子,执行成功

      a 的值为 207

      clear 为合法句子,执行成功

      ab =  语句出现语法错误!

    结语

      寒假在家想尝试着做一个C语言的编译器,这几天在家里研究编译原理的龙书,顺带就把上学期编译原理的课程设计整理下发到BLOG上。

      说实话龙书里面的内容挺难的,我学过编译原理的,但是还在在第二章就卡住了,所以说我们的课程知识还是学得很浅的。这段时间还是先把基础打的牢固些吧,研究龙书一段时间,然后考虑如何做这个编译器。过几天应该就要开始着手做了,到时候开发的文档和学到的一些新知识应该都会更新到BLOG上,也算是对自己的一种总结吧。

  • 相关阅读:
    七牛大数据平台的演进与大数据分析实践--转
    Re:从0开始的微服务架构:(一)重识微服务架构--转
    Re:从 0 开始的微服务架构--(三)微服务架构 API 的开发与治理--转
    Java7里try-with-resources分析--转
    线上服务CPU100%问题快速定位实战--转
    Windows下本机简易监控系统搭建(Telegraf+Influxdb+Grafana)--转
    Scalable, Distributed Systems Using Akka, Spring Boot, DDD, and Java--转
    ES Segment Memory——本质上就是segment中加到内存的FST数据,因此segment越多,该内存越大
    Self Organizing Maps (SOM): 一种基于神经网络的聚类算法
    RBF网络——核心思想:把向量从低维m映射到高维P,低维线性不可分的情况到高维就线性可分了
  • 原文地址:https://www.cnblogs.com/H-Vking/p/5171374.html
Copyright © 2011-2022 走看看