编译原理解释器(三)C语言语义分析器的实现

您所在的位置:网站首页 c语言编译器出错原因分析 编译原理解释器(三)C语言语义分析器的实现

编译原理解释器(三)C语言语义分析器的实现

2024-07-13 04:03| 来源: 网络整理| 查看: 265

“semantic”是语义分析器。语义分析器的输入流是语法树,根据对语法树的语义分析,在输出中用指定的颜色标记出指定的点。当无数个指定的点被依次标记出时,人眼认为“画”出了一条线。

要在VS上实现画出一条线有 2种方法:VC和BC。

“VC”是用Windows自带图形库实现的词法分析器,程序结果输出函数绘图语言解释器编译后的图形,通过改变main.cpp中的WinMain()Window程序主函数中,strcpy(SrcFilePath,"test1.txt");第二个参数来改变要读取的文件。“BC”是用EGE图形库实现的词法分析器,程序结果输出函数绘图语言解释器编译后的图形,通过改变main.cpp中的Parser()函数参数来改变要读取的文件。

 

step1

semantic.h

//#ifdef #endif 是预编译处理的宏语句 #ifdef _VC_COMPILER #include #include extern HDC hDC; #endif // _VC_COMPILER //“VC_Compiler”是用Windows自带图形库实现的词法分析器,程序结果输出函数绘图语言解释器编译后的图形 #ifdef _BC_COMPILER #include #include #endif // _BC_COMPILER #include"parser.h" //“BC_Compiler”是用EGE图形库实现的词法分析器,程序结果输出函数绘图语言解释器编译后的图形 #ifdef _VC_COMPILER #define red RGB(255,0,0) //红色 #define black RGB(0,0,0) //黑色 #endif // _VC_COMPILER #ifdef _BC_COMPILER #define white 255 //白色 #endif // _BC_COMPILER //----------外部函数声明 extern void DrawPixel(unsigned long x,unsigned long y);//绘制一个点 extern double GetExprValue(struct ExprNode* root);//获得表达式的值 extern void DrawLoop(double Start,double End,double Step,struct ExprNode* HorPtr,struct ExprNode* VerPtr);//图形绘制 extern void DelExprTree(struct ExprNode* root);//删除一棵树 #ifdef _BC_COMPILER extern int InGraphMode; extern int InitGraph(void); extern void CloseGraph(void); #endif // _BC_COMPILER

step2

semantic.c

#include"semantic.h" extern double Parameter,//参数T的存储空间:记录t每次加一点的变化 在语法分析中声明的 Origin_x,Origin_y,//横纵坐标平移距离 Scale_x,Scale_y,//横纵比例因子 Rot_angle;//旋转角度 double GetExprValue(struct ExprNode* root);//获得表达式的值 void DrawPixel(unsigned long x,unsigned long y);//绘制一个点 void DrawLoop(double Start,double End,double Step,struct ExprNode* HorPtr,struct ExprNode* VerPtr);//图形绘制 void DelExprTree(struct ExprNode* root);//删除一棵树 static void Errmsg(char *string);//出错处理 static void CalcCoord(struct ExprNode *Hor_Exp,struct ExprNode *Ver_Exp,double &Hor_x,double &Ver_y);//计算点的坐标 //----------出错处理 void Errmsg(char *string) { exit(1); } //----------计算被绘制点的坐标 static 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; //返回变换后点的坐标 }//没有返回值 //----------循环绘制点的坐标 void DrawLoop(double Start,//起始 double End,//终止 double Step,//步长 struct ExprNode* HorPtr,//横坐标表达式语法树的根节点 struct ExprNode* VerPtr)//纵坐标表达式语法树的根节点 { extern double Parameter; double x,y; for(Parameter=Start;ParameterOpCode) { //二元运算符 case PLUS : return GetExprValue(root->Content.CaseOperater.Left)+GetExprValue(root->Content.CaseOperater.Right); case MINUS : return GetExprValue(root->Content.CaseOperater.Left)-GetExprValue(root->Content.CaseOperater.Right); case MUL : return GetExprValue(root->Content.CaseOperater.Left)*GetExprValue(root->Content.CaseOperater.Right); case DIV : return GetExprValue(root->Content.CaseOperater.Left)/GetExprValue(root->Content.CaseOperater.Right); case POWER : return pow(GetExprValue(root->Content.CaseOperater.Left),GetExprValue(root->Content.CaseOperater.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; }//返回值是表达式的值 } //----------删除一颗语法树 void DelExprTree(struct ExprNode *root) { if(root==NULL) return; switch(root->OpCode) { case PLUS : //二元::两个孩子的内部节点 case MINUS : case MUL : case DIV : case POWER : DelExprTree(root->Content.CaseOperater.Left); DelExprTree(root->Content.CaseOperater.Right); break; case FUNC : //一元::一个孩子的内部节点 DelExprTree(root->Content.CaseFunc.Child); break; default : //叶子节点 break; } delete(root); //删除节点 } #ifdef _BC_COMPILER int INGraphMode = 0; int InitGraph(void) { int gd=DETECT,gm; if(InGraphMode) return; registerbgidriver(EGAVGA_driver); initgraph(&gd,&gm,""); setcolor(-1); InGraphMode=1; return 1; } void CloseGraph(void) { if(!InGraphMode) return; getch(); closegraph(); InGraphMode=0; } #endif // _BC_COMPILER //----------绘制一个点 void DrawPixel(unsigned long x,unsigned long y) { #ifdef _VC_COMPILER SetPixel(hDC,x,y,black); #endif // _VC_COMPILER #ifdef _BC_COMPILER putpixel(x,y,red); #endif // _BC_COMPILER }

 step3

BC方法

#include"semantic.h" int main() { if(!InitGraph()) return -1; Parser("test4.txt"); CloseGraph(); return 0; }

VC方法

#include"semantic.h" #define MAX_CHARS 200 HDC hDC; //窗口句柄,全局变量 char SrcFilePath[MAX_CHARS]; //用于存放源程序文件路径 static char Name[]="Compiler"; //窗口名 //----------初始化窗口函数声明 static bool PrepareWindow(HINSTANCE,HINSTANCE,int); //----------检查源程序文件是否合法函数声明 static bool CheckSrcFile(LPSTR); //----------窗口消息处理函数声明 static LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //----------转换函数 wchar_t * ChartoWChar(char *CStr) { size_t len = strlen(CStr) + 1; size_t converted = 0; wchar_t *WStr; WStr = (wchar_t*)malloc(len*sizeof(wchar_t)); mbstowcs_s(&converted, WStr, len, CStr, _TRUNCATE); return WStr; } //----------Window程序主函数 int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { //保存原文件路径 strcpy(SrcFilePath,"test5.txt"); //初始化窗口 if(PrepareWindow(hInstance,hPrevInstance,nCmdShow)!=true) { MessageBox(NULL, ChartoWChar("Window Initialize failed !"), ChartoWChar("ERROR !"),MB_OK); return 1; } //检查要分析的源程序文件 if(!CheckSrcFile(SrcFilePath)) return 1; //------------------------------------ //调用绘图语言解释器 Parser(SrcFilePath); //------------------------------------ //进入window消息循环 MSG Msg; while(GetMessage(&Msg,NULL,0,0)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } //----------初始化窗口函数实现 bool PrepareWindow(HINSTANCE hInst,HINSTANCE hPrevInstance,int nCmdShow) { HWND hWnd; WNDCLASS W; memset(&W,0,sizeof(WNDCLASS)); W.style=CS_HREDRAW|CS_VREDRAW; W.lpfnWndProc=WndProc; W.hInstance=hInst; W.hCursor=LoadCursor(NULL,IDC_ARROW); W.hbrBackground=(HBRUSH)(COLOR_WINDOW+1); W.lpszClassName= ChartoWChar(Name); RegisterClass(&W); hWnd=CreateWindow(ChartoWChar(Name), ChartoWChar(Name),WS_OVERLAPPEDWINDOW,10,10,740,490,NULL,NULL,hInst,NULL); if(hWnd==NULL) return false; ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); SetCursor(LoadCursor(hInst,IDC_ARROW)); hDC=GetDC(hWnd); return true; } //----------检查源程序文件是否合法函数实现 bool CheckSrcFile(LPSTR lpszCmdParam) { FILE *file=NULL; if(strlen(lpszCmdParam)==0) { MessageBox(NULL, ChartoWChar("Source File Not Specified "), ChartoWChar("ERROR"), MB_OK); return false; } if((file=fopen(lpszCmdParam,"r"))==NULL) { MessageBox(NULL, ChartoWChar("Open Source File Error !"), ChartoWChar("ERROR"),MB_OK); MessageBox(NULL, ChartoWChar(lpszCmdParam), ChartoWChar("Filename"),MB_OK); return false; } else fclose(file); return true; } //----------窗口处理函数实现 LRESULT CALLBACK WndProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam) { switch(Message) { case WM_DESTROY : ReleaseDC(hWnd,hDC); PostQuitMessage(0); return 0; //break; case WM_PAINT: PAINTSTRUCT pt; BeginPaint(hWnd,&pt); Parser(SrcFilePath); EndPaint(hWnd,&pt); default : return DefWindowProc(hWnd,Message,wParam,lParam); } }

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3