函数绘图语言解释器

一、实验目的

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

<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++提供的机制可提高程序的可读性与可维护性;低层次的语言支持机制,可以给程序员以更大的灵活性,并产生更高效的目标代码;

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

 

posted @ 2019-06-30 00:23  库妍  阅读(1040)  评论(0编辑  收藏  举报