?? parser.cpp
字號:
#include"parser.h"
#ifndef PARSER_DEBUG
#include"semantic.h"
#endif
#ifdef PARSER_DEBUG
#define enter(x) printf("enter in ");printf(x);printf("\n")
#else
#define enter(x)
#endif
#ifdef PARSER_DEBUG
#define back(x) printf("exit from "); printf(x); printf("\n")
#else
#define back(x)
#endif
#ifdef PARSER_DEBUG
#define call_match(x) printf("matchtoken ");printf(x);printf("\n");
#else
#define call_match(x);
#endif
#ifdef PARSER_DEBUG
#define Tree_trace(x) PrintSyntaxTree(x,1);
#else
#define Tree_trace
#endif
#ifdef PARSER_DEBUG
double Parameter=0; //參數T的存儲空間
#else
double Parameter=0, //參數T的存儲空間
Origin_x=0,Origin_y=0, //橫、縱平移距離
Scale_x=1,Scale_y=1, //橫、縱比例因子
Rot_angle=0; //旋轉角度
#endif
static Token token; //記號
//--------------輔助函數聲明
static void FetchToken();
static void MatchToken(enum Token_Type AToken);
static void SyntaxError(int case_of);
static void ErrMsg(unsigned LineNo,char *descrip,char *string );
static void PrintSyntaxTree(struct ExprNode *root,int indent);
//-------------非終結符的遞歸子程序聲明
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();
//--------------外部接口與語法樹構造函數聲明
extern void Parser(char *SrcFilePtr);
static struct ExprNode *MakeExprNode(enum Token_Type opcode,...);
//--------------通過詞法分析器接口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,char *descrip,char *string)
{
#ifdef PARSER_DEBUG
printf("Line No %5d:%s%s!\n",LineNo,descrip,string);
#else
char msg[256];
memset(msg,0,256);
sprintf(msg,"Line No %5d:%s%s!",LineNo,descrip,string);
#endif
#ifdef _VC_COMPILER
MessageBox(NULL,msg,"error!",MB_OK);
#endif
#ifdef _BC_COMPILER
printf("%s\n",msg);
#endif
CloseScanner();
exit(1);
}
//----------------------------------
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 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)
{
enter("Parser");
if(!InitScanner(SrcFilePtr)) //初始化詞法分析器
{printf("Open Source File Error!\n");return;}
FetchToken(); //獲取第一個記號
Program(); //遞歸下降分析
CloseScanner(); //關閉詞法分析器
back("Parser");
return;
}
//---------------------------Program的遞歸子程序
static void Program()
{
enter("Program");
while(token.type!=NONTOKEN)
{
Statement();
MatchToken(SEMICO);
}
back("Program");
}
//------------------------Statement的遞歸子程序
static void Statement()
{
enter("Statement");
switch(token.type)
{
case ORIGIN: OriginStatement(); break;
case SCALE: ScaleStatement(); break;
case ROT: RotStatement(); break;
case FOR: ForStatement(); break;
default: SyntaxError(2);
}
back("Statement");
}
//---------------------OriginStatement的遞歸子程序
static void OriginStatement(void)
{
struct ExprNode *tmp;
enter("OriginStatement");
MatchToken(ORIGIN);
MatchToken(IS);
MatchToken(L_BRACKET);
tmp=Expression();
#ifndef PARSER_DEBUG
Origin_x=GetExprValue(tmp); //獲取橫坐標的平移距離
DelExprTree(tmp);
#endif
MatchToken(COMMA);
tmp=Expression();
#ifndef PARSER_DEBUG
Origin_y=GetExprValue(tmp); //獲取縱坐標的平移距離
DelExprTree(tmp);
#endif
MatchToken(R_BRACKET);
back("OriginStatement");
}
//-----------------ScaleStatement的遞歸子程序
static void ScaleStatement(void)
{
struct ExprNode *tmp;
enter("ScaleStatement");
MatchToken(SCALE);
MatchToken(IS);
MatchToken(L_BRACKET);
tmp=Expression();
#ifndef PARSER_DEBUG
Scale_x=GetExprValue(tmp); //獲取橫坐標的比例因子
DelExprTree(tmp);
#endif
MatchToken(COMMA);
tmp=Expression();
#ifndef PARSER_DEBUG
Scale_y=GetExprValue(tmp); //獲取縱坐標的比例因子
DelExprTree(tmp);
#endif
MatchToken(R_BRACKET);
back("ScaleStatement");
}
//---------------------RotStatement的遞歸子程序
static void RotStatement(void)
{
struct ExprNode *tmp;
enter("RotStatement");
MatchToken(ROT);
MatchToken(IS);
tmp=Expression();
#ifndef PARSER_DEBUG
Rot_angle=GetExprValue(tmp); //獲取旋轉角度
DelExprTree(tmp);
#endif
back("RotStatement");
}
//------------------ForStatement的遞歸子程序
static void ForStatement(void)
{
#ifndef PARSER_DEBUG
double Start,End,Step; //繪圖起點、終點、步長
#endif
struct ExprNode *start_ptr,*end_ptr,*step_ptr,
*x_ptr,*y_ptr; //各表達式語法樹根結點指針
enter(" ForStatement");
MatchToken(FOR); call_match("FOR");
MatchToken(T); call_match("T");
MatchToken(FROM); call_match("FROM");
start_ptr=Expression(); //構造參數起點表達式
#ifndef PARSER_DEBUG
Start=GetExprValue(start_ptr); //計算參數起點表達式的值
DelExprTree(start_ptr); //釋放參數起點語法數所占空間
#endif
MatchToken(TO);call_match("TO");
end_ptr=Expression(); //構造參數表達式語法數
#ifndef PARSER_DEBUG
End=GetExprValue(end_ptr); //計算參數終點表達式的值
DelExprTree(end_ptr); //釋放參數終點語法數所占空間
#endif
MatchToken(STEP); call_match("STEP");
step_ptr=Expression(); //構造參數步長表達式語法樹
#ifndef PARSER_DEBUG
Step=GetExprValue(step_ptr); //計算參數步長表達式的值
DelExprTree(step_ptr); //釋放參數步長語法數所占空間
#endif
MatchToken(DRAW); call_match("DRAW");
MatchToken(L_BRACKET); call_match("(");
x_ptr=Expression(); //構造橫坐標表達式語法數
MatchToken(COMMA); call_match(",");
y_ptr=Expression(); //構造縱坐標表達式語法數
MatchToken(R_BRACKET); call_match(")");
#ifndef PARSER_DEBUG
// DrawLoop(Start,End,Step,x_ptr,y_ptr); //繪制圖形
DelExprTree(x_ptr); //釋放橫坐標語法數所占空間
DelExprTree(y_ptr); //釋放縱坐標語法數所占空間
#endif
back("ForStatement");
}
//-------------------------Expression的遞歸子程序
static struct ExprNode *Expression()
{
struct ExprNode *left,*right; //左右子數結點的指針
Token_Type token_tmp; //當前記號
enter("Expression");
left=Term(); //分析左操作樹且得到其語法數
while(token.type==PLUS||token.type==MINUS)
{
token_tmp=token.type;
MatchToken(token_tmp);
right=Term(); //分析右操作樹且得到其語法數
left=MakeExprNode(token_tmp,left,right); //構造運算的語法數結果為左子數
}
Tree_trace(left); //打印表達式的語法數
back("Expression");
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,*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;
}
//------------------生成語法樹的一個結點
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;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -