语法制导翻译绘制函数图形幻灯片.ppt
语法制导翻译绘制函数图形第1页,共20页,编辑于2022年,星期二1简单复习-函数f(t)=t的图形origin is(200,300);-设置原点的偏移量rot is pi/6;-设置旋转角度scale is(2,1);-设置横坐标和纵坐标的比例for T from 0 to 200 step 1 draw(t,0);-横坐标的轨迹for T from 0 to 180 step 1 draw(0,-t);-纵坐标的轨迹for T from 0 to 150 step 1 draw(t,-t);-f(t)=t的轨迹词法分析器:识别输入序列,并为语法分析器提供记号。语法分析器:根据记号流识别句子,并为表达式构造语法树。语义分析器:根据语言结构,处理函数绘图语言程序的语义。第2页,共20页,编辑于2022年,星期二21.表达式值的计算:深度优先后序遍历语法树 2.图形的绘制:画出每个坐标点绘图所需的语义处理:2.3.3 语法制导翻译绘制图形 从origin、rot和scale中得到坐标变换所需的信息;for_draw语句根据t的每一个值进行如下处理:a)计算被绘制点的横、纵坐标值;b)根据坐标变换信息进行坐标变换,得到实际坐标;c)根据点的实际坐标画出该点。2.3.3.1 绘图语言的语义 第3页,共20页,编辑于2022年,星期二3语法制导翻译的基本步骤 为文法符号设计属性();设计语义规则中所需的辅助函数;为产生式设计语义规则(不考虑实现时是语法制导定义)。比例设置语句的文法如下:ScaleStatment SCALE IS L_BRACKET Expression COMMA Expression R_BRACKET可简写为:S SCALE IS(E,E)此语句的作用是提供横、纵坐标的比例因子。因此:设计属性:.x和.y,分别保存比例因子;设计计算表达式值的辅助函数:get_value(nptr),它返回表达式的值;设计语义规则:S SCALE IS(E1,E2)S.x:=get_value(E1.nptr);S.y:=get_value(E2.nptr);第4页,共20页,编辑于2022年,星期二42.3.3.2 语义函数的设计 全程变量:(类似于设计属性)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;/用于记录比例因子例:以点(350,220)为圆心绘制两个同心园origin is(350,220);/Origin_x=350,Origin_y=220 scale is(50,50);/Scale_x=50,Scale_y=50 for t from 0 to 2*pi step pi/100 draw(cos(t),sin(t);scale is(100,100);/Scale_x=100,Scale_y=100 for t from 0 to 2*pi step pi/200 draw(cos(t),sin(t);第5页,共20页,编辑于2022年,星期二5 辅助语义函数a)计算表达式的值:深度优先后序遍历语法树 double GetExprValue(struct ExprNode*root);b)*计算点的坐标值:首先获取坐标值,然后进行坐标变换static void CalcCoord(struct ExprNode*Hor_Exp,struct ExprNode*Ver_Exp,double&Hor_x,double&Ver_y);c)绘制一个点(与环境有关):void DrawPixel(unsigned long x,unsigned long y);d)循环绘制所有的点:void DrawLoop(double Start,double End,double Step,struct ExprNode*HorPtr,struct ExprNode*VerPtr);第6页,共20页,编辑于2022年,星期二6 辅助语义函数设计举例 a)表达式值的计算 b)点轨迹的循环绘制void DrawLoop(double Start,double End,double Step,struct ExprNode*HorPtr,struct ExprNode*VerPtr)extern double Parameter;/参数T的存储空间double x,y;for(Parameter=Start;Parameter=End;Parameter+=Step)CalcCoord(HorPtr,VerPtr,x,y);/计算实际坐标 DrawPixel(unsigned long)x,(unsigned long)y);/根据坐标绘制点第7页,共20页,编辑于2022年,星期二72.3.3.3 递归子程序中语义规则的嵌入a)OriginStatementb)ForStatement 语义规则可以嵌入在递归子程序的任何位置。根据语法制导翻译语义规则可以嵌入在递归子程序的任何位置。根据语法制导翻译的基本思想,如果希望从某部分语言结构中获取语义,则相应的语义的基本思想,如果希望从某部分语言结构中获取语义,则相应的语义规则可以紧跟在该结构的语法分析之后。规则可以紧跟在该结构的语法分析之后。第8页,共20页,编辑于2022年,星期二8 2.3.3.4 解释器的主程序(略)2.3.3.5 测试例程与测试结果(略)2.3.3.6 解释器的源程序组织(看实际环境)程序的冗余比数据的冗余更危险;资源的物理位置与逻辑位置无关;合理组织资源,利于团队合作与回归测试;辅助信息同等重要。第9页,共20页,编辑于2022年,星期二92.5 上机题的改进建议 2.5.1 函数绘图语言的扩充 修改显示屏的直角坐标系,使得它与习惯上的坐标系一致;扩充语句类型,使得用户可以规定图形颜色;扩展循环绘图语句,使得for_draw语句可以嵌套;增加文本框,使得用户可以在图形中添加文字说明;增加清图功能,使得图形可以具有简单的动画效果。第10页,共20页,编辑于2022年,星期二102.5.2 采用面向对象技术实现解释器 语法制导翻译的本质反映在面向对象的程序设计方法上就是一种继承关系。类主程序习惯上:提供服务者(server)类请求服务者(client)主程序词法分析:语法分析:语义分析:第11页,共20页,编辑于2022年,星期二11static void ForStatement(void)tree_node_ptr start_ptr,end_ptr,step_ptr,x_ptr,y_ptr;#ifndef PARSER_DEBUG double start_val,end_val,step_val;/起点、终点、步长#endifMatchToken(FOR);MatchToken(T);MatchToken(FROM);start_ptr=Expression();/起点表达式的语法树MatchToken(TO);end_ptr=Expression();/终点表达式的语法树MatchToken(STEP);step_ptr=Expression();/步长表达式的语法树MatchToken(DRAW);MatchToken(L_BRACKET);x_ptr=Expression();MatchToken(COMMA);y_ptr=Expression();MatchToken(R_BRACKET);#ifndef PARSER_DEBUG start_val=GetExprValue(start_ptr);/起点值 end_val =GetExprValue(end_ptr);/终点值 step_val =GetExprValue(step_ptr);/步长值 DrawLoop(start_val,end_val,step_vak,x_ptr,y_ptr);/绘制图形 DelExprTree(start_ptr);DelExprTree(end_ptr);/释放空间 DelExprTree(step_ptr);DelExprTree(x_ptr);DelExprTree(y_ptr);#endif第12页,共20页,编辑于2022年,星期二12 不利用类机制 tree_node_ptr start_ptr,end_ptr,step_ptr,x_ptr,y_ptr,angle_ptr;void for_statement_syntax()/for_statement的语法分析match_token(FOR);match_token(T);match_token(FROM);start_ptr=expression();match_token(TO);end_ptr =expression();match_token(STEP);step_ptr =expression();match_token(DRAW);match_token(L_BRACKET);x_ptr=expression();match_token(COMMA);y_ptr=expression();match_token(R_BRACKET);void for_statement_semantics()/for_statement的语义分析double start_val,end_val,step_val;for_statement_syntax();/语法分析获取各表达式的语法树start_val=GetExprValue(start_ptr);/计算各表达式的值并绘图end_val =GetExprValue(end_ptr);step_val =GetExprValue(step_ptr);DrawLoop(start_val,end_val,step_val,x_ptr,y_ptr);DelExprTree(start_ptr);/释放空间DelExprTree(end_ptr);DelExprTree(step_ptr);DelExprTree(x_ptr);DelExprTree(y_ptr);第13页,共20页,编辑于2022年,星期二13 利用类机制 tree_node_ptr start_ptr,end_ptr,step_ptr,x_ptr,y_ptr,angle_ptr;void parser_class:for_statement()/基类中的for_statementmatch_token(FOR);match_token(T);match_token(FROM);start_ptr=expression();match_token(TO);end_ptr =expression();match_token(STEP);step_ptr =expression();match_token(DRAW);match_token(L_BRACKET);x_ptr=expression();match_token(COMMA);y_ptr=expression();match_token(R_BRACKET);void interpreter_class:for_statement()/派生类中的for_statementdouble start_val,end_val,step_val;parser_class:for_statement();/语法分析获取各表达式的语法树start_val=GetExprValue(start_ptr);/计算各表达式的值并绘图end_val =GetExprValue(end_ptr);step_val =GetExprValue(step_ptr);DrawLoop(start_val,end_val,step_val,x_ptr,y_ptr);DelExprTree(start_ptr);/释放空间DelExprTree(end_ptr);DelExprTree(step_ptr);DelExprTree(x_ptr);DelExprTree(y_ptr);第14页,共20页,编辑于2022年,星期二14 程序设计方法与程序设计语言支持方法无必然联系;C+对C的发展不仅是提供了对面向对象方法的支持,还扩展了常量定义、类属机制、异常处理,等等;灵活利用C+提供的机制可提高程序的可读性与可维护性。发挥你的聪明才智!第15页,共20页,编辑于2022年,星期二15double GetExprValue(struct ExprNode*root)if(root=NULL)return 0.0;switch(root-OpCode)case PLUS :return GetExprValue(root-Content.CaseOperator.Left)+GetExprValue(root-Content.CaseOperator.Right);case MINUS:./其它二元运算类似处理 case POWER:return pow(GetExprValue(root-Content.CaseOperator.Left),GetExprValue(root-Content.CaseOperator.Right);case FUNC :return(*root-Content.CaseFunc.MathFuncPtr)(GetExprValue(root-Content.CaseFunc.Child);case CONST_ID:return root-Content.CaseConst;case T :return*(root-Content.CaseParmPtr);default :return 0.0;(返回)第16页,共20页,编辑于2022年,星期二16void DrawLoop(double Start,double End,double Step,struct ExprNode*HorPtr,struct ExprNode*VerPtr)extern double Parameter;double x,y;for(Parameter=Start;Parameter=End;Parameter+=Step)CalcCoord(HorPtr,VerPtr,x,y);/计算点的实际坐标DrawPixel(unsigned long)x,(unsigned long)y);/根据坐标绘制点第17页,共20页,编辑于2022年,星期二17static void CalcCoord(struct ExprNode*Hor_Exp,struct ExprNode*Ver_Exp,double&Hor_x,double&Ver_y)double HorCord,VerCord,Hor_tmp;HorCord=GetExprValue(Hor_Exp);/计算点的原始坐标VerCord=GetExprValue(Ver_Exp);HorCord*=Scale_x;/比例变换VerCord*=Scale_y;/旋转变换Hor_tmp=HorCord*cos(Rot_angle)+VerCord*sin(Rot_angle);VerCord=VerCord*cos(Rot_angle)-HorCord*sin(Rot_angle);HorCord=Hor_tmp;HorCord+=Origin_x;/平移变换VerCord+=Origin_y;/返回变换后点的坐标Hor_x=HorCord;Ver_y=VerCord;返回第18页,共20页,编辑于2022年,星期二18static void OriginStatement(void)double x,y;struct ExprNode*tmp;MatchToken(ORIGIN);MatchToken(IS);MatchToken(L_BRACKET);tmp=Expression();x=GetExprValue(tmp);/获取横坐标的平移值 MatchToken(COMMA);tmp=Expression();y=GetExprValue(tmp);/获取纵坐标的平移值MatchToken(R_BRACKET);SetOrigin(x,y);/置坐标平移全程量 返回第19页,共20页,编辑于2022年,星期二19static void ForStatement(void)double Start,End,Step;struct ExprNode*start_ptr,*end_ptr,*step_ptr,*x_ptr,*y_ptr;MatchToken(FOR);MatchToken(T);MatchToken(FROM);start_ptr=Expression();Start=GetExprValue(start_ptr);MatchToken(TO);end_ptr=Expression();End=GetExprValue(end_ptr);MatchToken(STEP);step_ptr=Expression();Step=GetExprValue(step_ptr);MatchToken(DRAW);MatchToken(L_BRACKET);x_ptr=Expression();MatchToken(COMMA);y_ptr=Expression();MatchToken(R_BRACKET);DrawLoop(Start,End,Step,x_ptr,y_ptr);返回第20页,共20页,编辑于2022年,星期二20