📄 bianyi.cpp
字号:
#include<iostream.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<ctype.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//出错记号
};
struct Token{
Token_Type type;
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,NULL},
{FUNC,"SIN",0,sin},
{FUNC,"COS",0,cos},
{FUNC,"TAN",0,tan},
{FUNC,"LOG",0,log},
{FUNC,"EXP",0,exp},
{FUNC,"SQRT",0,sqrt},
{ORIGIN,"ORIGIN",0,NULL},
{SCALE,"SCALE",0,NULL},
{ROT,"ROT",0,NULL},
{IS,"IS",0,NULL},
{FOR,"FOR",0,NULL},
{FROM,"FROM",0,NULL},
{TO,"TO",0,NULL},
{STEP,"STEP",0,NULL},
{DRAW,"DRAW",0,NULL},
{ERRTOKEN,"ERRTOKEN",0,NULL}
};
const int TOKEN_LEN=100;
unsigned int LineNo;
static FILE *InFile;
static char TokenBuffer[TOKEN_LEN];
int InitScanner(const char*FileName){//初始化词法分析器
LineNo=1;
InFile=fopen(FileName,"r");
if(InFile!=NULL)return 1;
else return 0;
}
void CloseScanner(){//关闭词法分析器
if(InFile!=NULL)fclose(InFile);
}
static char GetChar(){//从源程序中读入一个字符
int Char=getc(InFile);
return toupper(Char);
}
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 i;
for(i=0;i<sizeof(TokenTab)/sizeof(TokenTab[0]);i++){
if(strcmp(TokenTab[i].lexeme,IDString)==0)
return TokenTab[i];
}
Token errortoken;
memset(&errortoken,0,sizeof(Token));
errortoken.type=ERRTOKEN;
return errortoken;
}
static void BackChar(char Char){
if(Char!=EOF)ungetc(Char,InFile);
}
extern Token GetToken(void){
Token token;
int Char;
memset(&token,0,sizeof(Token));
EmptyTokenString();
token.lexeme=TokenBuffer;
for(;;){
Char=GetChar();
if(Char==EOF){
token.type=NONTOKEN;
return token;
}
if(Char=='\n')LineNo++;
if(!isspace(Char))break;
}//end of for
AddCharTokenString(Char);
if(isalpha(Char)){
for(;;){
Char=GetChar();
if(isalnum(Char))
AddCharTokenString(Char);
else break;
}
BackChar(Char);
token=JudgeKeyToken(TokenBuffer);
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
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();
}//end of if
else{
BackChar(Char);
token.type=MINUS;
break;
}//end of else
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;
break;
}
else{
BackChar(Char);
token.type=MUL;
break;
}
default:token.type=ERRTOKEN;break;
}//end of switch
}//end of close
return token;
}
typedef double (*MathFuncPtr)(double);
typedef double (*FuncPtr)(double);
struct ExprNode{//语法树节点类型
enum Token_Type OpCode;
union{
struct{ExprNode *Left,*Right;}CaseOperator;
struct{ExprNode *Child;FuncPtr MathFuncPtr;}CaseFunc;
double CaseConst;
double *CaseParmPtr;
}Content;
};
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();
//外部接口与语法树构造函数声明
static struct ExprNode *MakeExprNode(enum Token_Type opcode,...);
extern void Parser(char *SrcFilePtr);
//....................................//
static void FetchToken(){//通过语法分析器接口GetToken()获取一个记号
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){//打印错误信息
cout<<"Line No!"<<LineNo<<" "<<descrip<<" "<<string;
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 main(int argc,char *argv[]){
Token token;
if(argc<2){
cout<<"请输入源文件!"<<endl;
return;
}
if(!InitScanner(argv[1])){
cout<<"打开文件失败!"<<endl;
}
cout<<"记号类别 字符串 常数值 函数指针"<<endl;
cout<<"---------------------------------------------------------"<<endl;
while(1){
token=GetToken();
if(token.type!=NONTOKEN){
cout<<token.type<<" ";
cout<<token.lexeme<<" ";
cout<<token.value<<" ";
cout<<token.Funcptr<<endl;
}
else break;
}
cout<<"-----------------------------------------------------"<<endl;
CloseScanner();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -