• 函数绘图语言解释器


    一、实验目的

    通过做上机题加深对编译器构造原理和方法的理解,巩固所学知识。

    <1> 会用正规式和产生式设计简单语言的语法;

    <2> 会用递归下降子程序编写编译器或解释器;

    <3> 会写上机报告。

    二、实验环境

    Dev C++ 5.11

    三、题目及要求

    为函数绘图语言编写一个解释器,解释器接受用绘图语言编写的源程序,经语法和语义分析之后,将源程序所规定的图形显示在显示屏(或窗口)中。通过自己动手编写解释器,掌握语言翻译特别是语言识别的基本方法。

    四、实验内容

    1、词法分析器的构造

    步骤:正规式-NFADFA-最小DFA-编写程序-测试

    1.1 记号的设计

    <1> 词法分析器的三个任务:

    1.滤掉源程序中的无用成分;

    2.输出记号供语法分析器使用;

    3.识别非法输入,并将其标记为“出错记号”。

    <2> 记号的组成:记号的类别和属性。

    <3> 记号的数据结构:

    struct Token // 记号的数据结构

    { Token_Type  type; // 类别

    char * lexeme; // 属性,原始输入的字符串

    double value; // 属性,若记号是常数则是常数的值

    double (* FuncPtr)(double);

    // 属性,若记号是函数则是函数指针

    };

    <4> 函数绘图语言中记号的分类与表示

    enum Token_Type   // 记号的类别,共22

    { ORIGIN, SCALE, ROT, IS,   // 保留字(一字一码)

    TO, STEP, DRAW,FOR, FROM, // 保留字

    T,   // 参数

    SEMICO, L_BRACKET, R_BRACKET, COMMA,// 分隔符

    PLUS, MINUS, MUL, DIV, POWER, // 运算符

    FUNC,   // 函数(调用)

    CONST_ID,   // 常数

    NONTOKEN,   // 空记号(源程序结束)

    ERRTOKEN   // 出错记号(非法输入)

    };

    1.2 模式的正规式表示

    1.3 区分记号的符号表

    2、语法分析器的构造

    2.1 语法分析器的任务:分析语言的结构

    1)为句子(表达式)构造语法树;

    2)检查程序(语句)中的语法错误。

    2.2 主要工作:

    1)设计函数绘图语言的文法,使其适合递归下降分析;

    2)设计语法树的节点,用于存放表达式的语法树;

    3)设计递归下降子程序,分析句子并构造表达式的语法树;

    4)设计测试程序和测试用例,检验分析器是否正确。

    2.3 函数绘图语言的文法
    <1> 文法

    Program   → ε| Program Statement SEMICO

    Statement →  OriginStatment | ScaleStatment

            |  RotStatment    | ForStatment

    OriginStatment ORIGIN IS

    L_BRACKET Expression COMMA Expression R_BRACKET

    ScaleStatment  SCALE IS

    L_BRACKET Expression COMMA Expression R_BRACKET

    RotStatment ROT IS Expression

    <2> 改写文法为无二义文法

    <3> 消除左递归和提取左因子

    消除program产生式的左递归

    Program    Program Statement SEMICO |ε

    Program   → ε Program

    Program’ →  Statement SEMICO Program|ε

    Program  Statement SEMICO Program |ε

    <4> 改写左结合的产生式为EBNF形式(避免子程序调用)

    改写为EBNF形式,以减少不必要的子程序调用。

    Program  { Statement SEMICO }的子程序:

    void Program()

    {  while (token != NONTOKEN)

       { Statement(); MathchToken(SEMICO); }

    }

    3、语法制导翻译绘制图形

    3.1 绘图语言的语义

    1)表达式值的计算:深度优先后序遍历语法树

    2)图形的绘制:画出每个坐标点

    3.2 绘图所需的语义处理:

    1)从originrotscale中得到坐标变换所需的信息;

    2for_draw语句根据t的每一个值进行如下处理:

    计算被绘制点的横、纵坐标值;

    根据坐标变换信息进行坐标变换,得到实际坐标;

    根据点的实际坐标画出该点。

    3.3 语法制导翻译的基本步骤

    1)为文法符号设计属性;

    2)设计语义规则中所需的辅助函数;

    3)为产生式设计语义规则。

    3.4 语义函数的设计

    <1> 全程变量:

    double Parameter=0;     // 为参数T分配的变量

    double Origin_x=0.0, Origin_y=0.0;// 用于记录平移距离

    double Rot_ang=0.0;     // 用于记录旋转角度

    double Scale_x=1, Scale_y=1;     // 用于记录比例因子

    <2> 辅助语义函数

    a) 计算表达式的值:深度优先后序遍历语法树

       double GetExprValue(struct ExprNode * root);

    b) 计算点的坐标值:首先获取坐标值,然后进行坐标变换

    static void CalcCoord( struct ExprNode * x_nptr,

      struct ExprNode * y_nptr,

      double &x_val,

      double &y_val);

    c) 绘制一个点(与环境有关):

    void DrawPixel(unsigned long x, unsigned long y);

    d) 循环绘制所有的点:

    void DrawLoop(  double Start,

     double End,

        double Step,

        struct ExprNode * HorPtr,

        struct ExprNode * VerPtr);

    4、解释器的源程序组织(看实际环境)

    一、心得体会

      C++C的发展不仅是提供了对面向对象方法的支持,还扩展了常量定义、类属机制、异常处理,等等;灵活利用C++提供的机制可提高程序的可读性与可维护性;低层次的语言支持机制,可以给程序员以更大的灵活性,并产生更高效的目标代码;

        通过编译原理的实验,在自已动手体验的情况下,我们更加透彻地理解了词法分析的过程以及该算法。对于以后由模型向程序代码的转化能力上,有了很大的锻炼。我们会更加专心的研究计算机知识,不断将现实中遇到的实际问题,向程序方面转变,做到灵活运用所学知识。

  • 相关阅读:
    centos7安装puppet详细教程(简单易懂,小白也可以看懂的教程)
    centos7.3下安装nginx
    JS实现转动随机数抽奖的特效代码
    【孤独旅者】封装一个三级联动和基于Vue的mintUI三级联动
    【孤独旅者】Vue-封装$on,$emit,$off
    数据可视化,选择Echarts还是Highcharts?
    关于redux和react-redux
    vue 封装一个插件
    vue实现点击回到顶部
    vue实现吸顶
  • 原文地址:https://www.cnblogs.com/ku1274755259/p/11108397.html
Copyright © 2020-2023  润新知