#include"scanner.h" typedef double(*FuncPtr)(double); //语法树的节点 struct ExprNode //type of syntax tree's node { enum Token_Type OpCode; //PLUS MINUS DIV POWER FUNC CONST_ID union { struct{ExprNode *Left,*Right;}CaseOperator; struct{ExprNode *Child;FuncPtr MathFuncPtr;}CaseFunc; double CaseConst; double * CaseParmPtr; }Content; }; extern void Parser(char *SrcFilePtr);//参数为字符串
#include <cstring> #include <cstdio> #include <cstdlib> #include <cmath> #include <SDKDDKVer.h> #include <stdio.h> #include <tchar.h> enum Token_Type // 记号的类别 { 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 }; typedef double (*MathFuncPtr)(double);//函数指针 struct Token // 记号的数据结构 { Token_Type type; // 类别 const char * lexeme; // 属性,原始输入的字符串 double value; // 属性,若记号是常数则是常数的值 double (* FuncPtr)(double); // 属性,若记号是函数则是函数的指针 }; static Token TokenTab[] = { {CONST_ID, "PI", 3.1415926, NULL}, {CONST_ID, "E", 2.71828, NULL}, {T, "T", 0.0, NULL}, {FUNC, "SIN", 0.0, sin}, {FUNC, "COS", 0.0, cos}, {FUNC, "TAN", 0.0, tan}, {FUNC, "LN", 0.0, log}, {FUNC, "EXP", 0.0, exp}, {FUNC, "SQRT", 0.0, sqrt}, {ORIGIN, "ORIGIN", 0.0, NULL}, {SCALE, "SCALE", 0.0, NULL}, {ROT, "ROT", 0.0, NULL}, {IS, "IS", 0.0, NULL}, {FOR, "FOR", 0.0, NULL}, {FROM, "FROM", 0.0, NULL}, {TO, "TO", 0.0, NULL}, {STEP, "STEP", 0.0, NULL}, {DRAW, "DRAW", 0.0, NULL} }; extern unsigned int LineNo; extern int InitScanner(const char*); extern Token GetToken(void); extern void CloseScanner(void);
#include<windows.h> #include<wingdi.h> #define red RGB(255,0,0) //红色 #define black RGB(0,0,0) //黑色 extern HDC hDC; //----------------外部函数声明 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); //删除一棵树
#include "semantics.h" #include <cmath> #include "parser.h" extern double Parameter, //参数T的存储空间 Origin_x, Origin_y, //横、纵平移距离 Scale_x, Scale_y, //横、纵比例因子 Rot_angle; extern HDC hDC; void DrawPixel(unsigned long x,unsigned long y); //绘制一个点 double GetExprValue(struct ExprNode *root); //获得表达式的值 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; Parameter <= End; Parameter += Step) { CalcCoord(HorPtr, VerPtr, x, y); DrawPixel((unsigned long)x, (unsigned long)y); } } //---------------计算表达式的值 double 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 : return GetExprValue(root->Content.CaseOperator.Left) - GetExprValue(root->Content.CaseOperator.Right); case MUL : return GetExprValue(root->Content.CaseOperator.Left) * GetExprValue(root->Content.CaseOperator.Right); case DIV : return GetExprValue(root->Content.CaseOperator.Left) / GetExprValue(root->Content.CaseOperator.Right); 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; } } //---------------删除一颗语法树 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.CaseOperator.Left); DelExprTree(root->Content.CaseOperator.Right); break; case FUNC : DelExprTree(root->Content.CaseFunc.Child); break; default : break; } delete(root); } //--------------绘制一个点 void DrawPixel(unsigned long x, unsigned long y) { SetPixel(hDC, x, y, black); }
#include "semantics.h" #include <stdio.h> #define MAX_CHARS 200 extern void Parser(char *SrcFilePtr); 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); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { //保存源文件路径 strcpy(SrcFilePath, "testerror.txt"); //初始化窗口 if(PrepareWindow(hInstance, hPrevInstance, nCmdShow)!=true) { MessageBox(NULL, "窗口初始化失败 !", "错误", MB_OK); return 1; } //检查要分析的源程序文件 if (!CheckSrcFile(SrcFilePath)) return 1; //---------------------------------------- // 调用绘图语言解释器 Parser(SrcFilePath); //---------------------------------------- //进入窗口消息循环 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 = Name; RegisterClass(&W); hWnd = CreateWindow(Name, Name, WS_OVERLAPPEDWINDOW, 225, 225, 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,"未指定源程序文件!", "Error", MB_OK); return false; } if((file=fopen(lpszCmdParam, "r"))==NULL) { MessageBox(NULL, "打开源程序文件出错!", "错误", MB_OK); MessageBox(NULL, lpszCmdParam, "文件名", 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; case WM_PAINT : PAINTSTRUCT pt; BeginPaint(hWnd, &pt); Parser(SrcFilePath); EndPaint(hWnd, &pt); default: return DefWindowProc(hWnd,Message,wParam, lParam); } }
#include "parser.h" #include <cstdio> #include <stdarg.h> #include "semantics.h" //构造语法树的目的是求表达式的值 //全是递归程序 double Parameter=0, //参数T的存储空间 Origin_x=0,Origin_y=0, //横、纵平移距离 Scale_x=1, Scale_y=1, //横、纵比例因子 Rot_angle=0; //旋转角度 static Token token; //----------------------辅助函数声明 static void FetchToken(); static void MatchToken(enum Token_Type AToken); static void SyntaxError(int case_of); static void ErrMsg(unsigned LineNo,const char *descrip,const char *string); static void PrintSyntaxTree(struct ExprNode *root,int indent);//打印语法树 //-----------------------外部接口与语法树构造声明函数 void Parser(char * SrcFilePtr); static struct ExprNode * MakeExprNode(enum Token_Type opcode,...); //---------------------非终结符的递归子程序声明 static void Program(); static void Statement(); static void OriginStatement(); static void RotStatement(); static void ScaleStatement(); static void ForStatement(); static struct ExprNode *Expression(); static struct ExprNode *Term(); static struct ExprNode *Factor(); static struct ExprNode *Component(); static struct ExprNode *Atom(); //-----------------------辅助函数 //通过词法分析器接口GetToken获取一个记号 static void FetchToken() { token = GetToken(); if(token.type == ERRTOKEN) SyntaxError(1); } //匹配记号 static void MatchToken(enum Token_Type The_Token) { if(token.type != The_Token) SyntaxError(2); FetchToken(); } //处理语法错误 static void SyntaxError(int case_of) { switch(case_of) { case 1 :ErrMsg(LineNo,"错误记号",token.lexeme);break; case 2 :ErrMsg(LineNo,"不是预期的记号",token.lexeme);break; } } //打印错误信息 void ErrMsg(unsigned LineNo,const char *descrip,const char *string) { printf("Line No %d: %s %s!\n",LineNo,descrip,string); char msg[256]; memset(msg, 0, 256); sprintf(msg, "Line No %d: %s %s",LineNo,descrip,string); MessageBox(NULL, msg, "Error!", MB_OK); CloseScanner(); exit(1); } //深度优先先序遍历语法树并打印 void PrintSyntaxTree(struct ExprNode *root,int indent) { int temp; for(temp = 1;temp <= indent;temp++)printf("\t"); switch(root->OpCode) //打印根节点 { case PLUS: printf("%s\n","+");break; case MINUS: printf("%s\n","-");break; case MUL: printf("%s\n","*");break; case DIV: printf("%s\n","/");break; case POWER: printf("%s\n","**");break; case FUNC: printf("%x\n", root->Content.CaseFunc.MathFuncPtr);break; case CONST_ID: printf("%f\n",root->Content.CaseConst);break; case T: printf("%s\n","T");break; default: printf("Error Tree Node! \n");exit(0); } if(root->OpCode == CONST_ID || root->OpCode == T) //叶子节点返回 return ; if(root->OpCode == FUNC) //递归打印一份孩子的节点 PrintSyntaxTree(root->Content.CaseFunc.Child,indent+1); else { PrintSyntaxTree(root->Content.CaseOperator.Left,indent+1); PrintSyntaxTree(root->Content.CaseOperator.Right,indent+1); } } //-------------------绘图解释器的外部接口 void Parser(char *SrcFilePtr) { if(!InitScanner(SrcFilePtr)) { printf("Open Source File Failed!\n"); } FetchToken(); Program(); CloseScanner(); } //----------------生成语法树的一个节点 static struct ExprNode* MakeExprNode(enum Token_Type opcode,...) { struct ExprNode *ExprPtr = new(struct ExprNode); ExprPtr->OpCode = opcode; //接受记号的类别 va_list ArgPtr; va_start (ArgPtr,opcode); switch(opcode) //根据记号的类别构造不同的记号 { case CONST_ID: ExprPtr->Content.CaseConst = (double)va_arg(ArgPtr,double); break; case T: ExprPtr->Content.CaseParmPtr = &Parameter; break; case FUNC: ExprPtr->Content.CaseFunc.MathFuncPtr = (FuncPtr)va_arg(ArgPtr,FuncPtr); ExprPtr->Content.CaseFunc.Child = (struct ExprNode *)va_arg(ArgPtr,struct ExprNode *); break; default: ExprPtr->Content.CaseOperator.Left = (struct ExprNode *)va_arg(ArgPtr,struct ExprNode *); ExprPtr->Content.CaseOperator.Right = (struct ExprNode *)va_arg(ArgPtr,struct ExprNode *); break; } va_end(ArgPtr); return ExprPtr; } //-------------------非终结符的递归子程序 //program的递归子程序 static void Program() { while(token.type != NONTOKEN) { Statement(); MatchToken(SEMICO); } } //statement的递归子程序 static void Statement() { switch(token.type) { case ORIGIN: OriginStatement(); break; case SCALE: ScaleStatement(); break; case ROT: RotStatement(); break; case FOR: ForStatement(); break; default: SyntaxError(2); } } //originstatement的递归子程序 static void OriginStatement() { struct ExprNode *tmp; MatchToken(ORIGIN); MatchToken(IS); MatchToken(L_BRACKET); tmp = Expression(); Origin_x = GetExprValue(tmp); DelExprTree(tmp); MatchToken(COMMA); tmp = Expression(); Origin_y = GetExprValue(tmp); DelExprTree(tmp); MatchToken(R_BRACKET); } //scalestatement的递归子程序 static void ScaleStatement() { struct ExprNode *tmp; MatchToken(SCALE); MatchToken(IS); MatchToken(L_BRACKET); tmp = Expression(); Scale_x = GetExprValue(tmp); DelExprTree(tmp); MatchToken(COMMA); tmp = Expression(); Scale_y = GetExprValue(tmp); DelExprTree(tmp); MatchToken(R_BRACKET); } //rotstatement的递归子程序 static void RotStatement() { struct ExprNode *tmp; MatchToken(ROT); MatchToken(IS); tmp = Expression(); Rot_angle = GetExprValue(tmp); DelExprTree(tmp); } //forstatement的递归子程序 static void ForStatement() { 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); DelExprTree(start_ptr); MatchToken(TO); end_ptr = Expression(); //构造参数终点表达式语法树 End = GetExprValue(end_ptr); DelExprTree(end_ptr); MatchToken(STEP); step_ptr = Expression(); //构造步长表达式语法树 Step = GetExprValue(step_ptr); DelExprTree(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); DelExprTree(x_ptr); DelExprTree(y_ptr); } //expression的递归子程序 static struct ExprNode * Expression() { struct ExprNode *left,*right; //左右子树节点的指针 Token_Type token_tmp; //当前记号 left = Term(); //分析左操作数且得到其语法树 while(token.type == PLUS || token.type == MINUS) { token_tmp = token.type; MatchToken(token_tmp); right = Term(); //分析右操作数且得到其语法树 left = MakeExprNode(token_tmp,left,right); //构造运算的语法树,结果为左子树 } return left; } //term的递归子程序 static struct ExprNode* Term() { struct ExprNode *left,*right; Token_Type token_tmp; left = Factor(); while(token.type == MUL || token.type == DIV) { token_tmp = token.type; MatchToken(token_tmp); right = Factor(); left = MakeExprNode(token_tmp,left,right); } return left; } //factor的递归子程序 static struct ExprNode* Factor() { struct ExprNode *left,*right; if(token.type == PLUS) //匹配一元加运算 { MatchToken(PLUS); right = Factor(); //表达式退化为仅有右操作数的表达式 } else if(token.type == MINUS) //匹配一元减运算 { MatchToken(MINUS); //表达式转化为二元减运算的表达式 right = Factor(); left = new ExprNode; left->OpCode = CONST_ID; left->Content.CaseConst = 0.0; right = MakeExprNode(MINUS,left,right); } else right = Component(); //匹配非终结符Component return right; } //component的递归子程序 static struct ExprNode* Component() { struct ExprNode *left,*right; left = Atom(); if(token.type == POWER) { MatchToken(POWER); right = Component(); //递归调用Component以实现POWER的右结合 left = MakeExprNode(POWER,left,right); } return left; } //atom的递归子程序 static struct ExprNode* Atom() { struct Token t = token; struct ExprNode *address=NULL,*tmp; switch (token.type) { case CONST_ID: MatchToken(CONST_ID); address = MakeExprNode(CONST_ID,t.value); break; case T: MatchToken(T); address = MakeExprNode(T); break; case FUNC: MatchToken(FUNC); MatchToken(L_BRACKET); tmp = Expression(); address = MakeExprNode(FUNC,t.FuncPtr,tmp); MatchToken(R_BRACKET); break; case L_BRACKET: MatchToken(L_BRACKET); address = Expression(); MatchToken(R_BRACKET); break; default: SyntaxError(2); } return address; }
#include "scanner.h" #include <cctype> #define TOKEN_LEN 100 unsigned int LineNo; static FILE *InFile; static char TokenBuffer[TOKEN_LEN]; extern int InitScanner(const char *FileName) { LineNo = 1; InFile = fopen(FileName, "r"); if(InFile != NULL) return 1; else return 0; } extern void CloseScanner(void) { if(InFile != NULL) fclose(InFile); } static char GetChar(void) { int Char = getc(InFile); return toupper(Char); } static void BackChar(char Char) { if(Char != EOF) ungetc(Char, InFile); } static void AddCharTokenString(char Char) { int TokenLength = strlen(TokenBuffer); if(TokenLength + 1 >= sizeof(TokenBuffer)) return; TokenBuffer[TokenLength] = Char; TokenBuffer[TokenLength+1] = '\0'; } static void EmptyTokenString(){ memset(TokenBuffer, 0, TOKEN_LEN); } //判断是否为合法标记 static Token JudgeKeyToken(const char *IDString) { int loop; for(loop=0; loop<sizeof(TokenTab)/sizeof(TokenTab[0]); loop++) { //遍历符号表 if(strcmp(TokenTab[loop].lexeme, IDString)==0) return TokenTab[loop]; } Token errortoken; memset(&errortoken, 0, sizeof(Token)); errortoken.type = ERRTOKEN; return errortoken; } //只是获得一个记号 extern Token GetToken() { Token token; int Char; memset(&token, 0, sizeof(Token)); EmptyTokenString();//memset(TokenBuffer) token.lexeme = TokenBuffer; for(;;) { Char = GetChar(); if(Char == EOF) { token.type = NONTOKEN; return token; } if(Char == '\n') LineNo++; if(!isspace(Char)) break; }//处理空格等 AddCharTokenString(Char); //主要就是三个if if(isalpha(Char)) { for(;;) { Char = GetChar(); if(isalnum(Char)) AddCharTokenString(Char); else break; } BackChar(Char); token = JudgeKeyToken(TokenBuffer); //返回的是一个新的token,不再是GetToken函数一开始声明的token token.lexeme = TokenBuffer; return token; } else if(isdigit(Char)) { for(;;) { Char = GetChar(); if(isdigit(Char)) AddCharTokenString(Char); else break; } //处理小数 if(Char == '.') { AddCharTokenString(Char); for(;;) { Char = GetChar(); if(isdigit(Char)) AddCharTokenString(Char); else break; } }//end of if(Char == '.') BackChar(Char); token.type = CONST_ID; token.value = atof(TokenBuffer); return token; } else { switch(Char) { case ';' : token.type = SEMICO; break; case '(' : token.type = L_BRACKET; break; case ')' : token.type = R_BRACKET; break; case ',' : token.type = COMMA; break; case '+' : token.type = PLUS; break; case '-' ://处理注释 Char = GetChar(); if(Char == '-') { while(Char != '\n' && Char != EOF) Char = GetChar(); BackChar(Char); return GetToken();//token函数的开始都会memset的 } else { BackChar(Char); token.type = MINUS; break; } case '/' : Char = GetChar(); if(Char == '/') { while(Char != '\n' && Char != EOF) Char = GetChar(); BackChar(Char); return GetToken(); } else { BackChar(Char); token.type = DIV; break; } case '*' : Char = GetChar(); if(Char == '*') { token.type = POWER; AddCharTokenString(Char); break; } else { BackChar(Char); token.type = MUL; break; } default : token.type = ERRTOKEN; break; }//end of switch return token; }//end of else(不是字母和数字,就是符号) }//end of GetToken /* int main() { Token token; char fname[100]; strcpy(fname, "test.txt"); if (!InitScanner(fname)) // 初始化词法分析器 { printf("Open Source File Error ! \n"); return 0; } printf("记号类别 字符串 常数值 函数指针\n"); printf("____________________________________________\n"); while (1) { token = GetToken(); // 通过词法分析器获得一个记号 if (token.type != NONTOKEN) // 打印记号的内容 printf("%4d %12s %12f %12x\n", token.type, token.lexeme, token.value, token.FuncPtr); else break; // 源程序结束,退出循环 }; printf("____________________________________________\n"); CloseScanner(); // 关闭词法分析器 return 0; } */