这是CMake的源代码.主要负责词汇的提取你可以调用它的CMake::get_token(),返回个CToken的类.
/// Make.h///
enum token_types{DELIMITER,VARIABLE,NUMBER,COMMAND, STRING,QUOTE,FINISHED,NONE,ENTER}; // 标记类型集合
#define TOKEN_MAX 80#define STRDELIMITER "+-*^/=;(),><" // 符号集合#define DIM 11 // Dim#define AS 12 // As#define INTEGER 13 // Integer#define PRINT 14 // Print
class CToken {public: char token[TOKEN_MAX]; int token_type; int tok;};
class CMake {public: CMake(char *Prog,int Proglength); virtual ~CMake();public: char *prog; int proglength; int isdelim(char c); // 如果是运算符号返回1,不是则返回0 int iswhite(char c); // 是空格返回1,不是则返回0 int look_up(char *c); // 返回COMMAND类型,c是COMMAND字符串的指针 CToken get_token(void); // 得到标记 int findchar(char *str,char ch); // 从str里找到ch,返回其在str里的引索;如果str里没有ch,则返回-1};
/
// Make.cpp: implementation of the CMake class.////
#include "stdafx.h"#include "Make.h"
//// Construction/Destruction//
CMake::CMake(char *Prog,int Proglength){ proglength=Proglength; prog=new char[Proglength+1]; strcpy(prog,Prog);}
CMake::~CMake(){ }
CToken CMake::get_token(void) { register char *temp; CToken m_token; m_token.token_type=0; m_token.tok=0; temp=m_token.token; if(*prog=='/0') { *m_token.token='/0'; m_token.tok=0; m_token.token_type=FINISHED; return m_token; } while(iswhite(*prog)) ++prog; if(*prog=='/r') // 如果是换行符 { m_token.token[0]=*prog; m_token.token[1]='/0'; m_token.token_type=ENTER; prog++; return m_token; } if( isdelim(*prog)) // 如果找得到运算符号标记 { *m_token.token=*prog; *(m_token.token+1)='/0'; m_token.tok=0; m_token.token_type=DELIMITER; prog++; return m_token; // 譬如 token[0]='+' token[1]='/0'; }
if(*prog=='"') // 如果是字符串 { prog++; int i=0; while(*prog!='"' && *prog!='/r') { m_token.token[i]=*prog; i++; prog++; } prog++; m_token.token[i]='/0'; m_token.token_type=QUOTE; return m_token; }
if( isdigit(*prog)) // 如果找到数字标记 { int i=0; while(isdigit(*prog) && i<TOKEN_MAX) // 小于token最长为80个字符 { m_token.token[i]=*prog; i++; prog++; } m_token.token[i]='/0'; m_token.token_type=NUMBER; return m_token; } if( isalpha(*prog)) // 如果是命令COMMAND或是一般标记STRING { int i=0; while(!isdelim(*prog) && *prog!=' ') // 不能是运算符号和空格 { m_token.token[i]=*prog; i++; prog++; } m_token.token[i]='/0'; if(look_up(m_token.token)) // 如果能查到它是命令COMMAND { m_token.token_type=COMMAND; m_token.tok=look_up(m_token.token); } else { m_token.token_type=STRING; } return m_token; }
m_token.token_type=NONE; prog++; return m_token;}
int CMake::iswhite(char c){ if(c==' '||c=='/t') return 1; else return 0;}
int CMake::isdelim(char c){ if( findchar(STRDELIMITER,*prog) >= 0 || c==9 || c=='/r' || c==0) return 1; return 0;}
int CMake::findchar(char *str,char ch) { int length=strlen(str); if(length>0) { for(int i=0;i<length;i++) if(str[i]==ch) return i; return -1; } else return -1;}
int CMake::look_up(char *c){ if(strcmp(c,"print")==0) return PRINT; if(strcmp(c,"Integer")==0) return INTEGER; if(strcmp(c,"Dim")==0) return DIM; if(strcmp(c,"As")==0) return AS;
return 0;}
这是执行代码的CExecutable封装
//// CExecutable.h
class CintMember{public: char name[64]; int value;};
class CExecutable {public: CExecutable(vector <CToken> tokens); virtual ~CExecutable(); void Run();private: vector <CToken> m_tokens; file://装所有标记的数据库 vector <CintMember> m_intArray; file://装所有int类型的变量 void Run_Print(int *index); file://*index是重要的m_tokens里的指针 void Run_Dim(int *index); file://~~ void Run_Assignment(int *index);// 赋值语句 file://Ai是辅助的意思,Ai_*()是辅助函数 int Ai_GetNextValue(void* result,int type,int *index); file://得到代数式的值result int Ai_GetVarNo(char *name,int *result,int type);//得到变量在Array中的引索result void get_exp(int *result,int *index); void level2(int *result,int *index); void level3(int *result,int *index); void level4(int *result,int *index); void level5(int *result,int *index); void level6(int *result,int *index); void primitive(int *result,int *index); void arith(char o,int *r,int *h); void serror(int error); int look_up(char *c); int find_var(char *var_name,void *value); // 查找变量,将变量值装在*value int Isvar(char *name); // 看name是否是变量,返回变量类型 0:什么都不是,1:Integer,2:string};
/
// Executable.cpp: implementation of the CExecutable class.////
#include "stdafx.h"#include "Executable.h"
//// Construction/Destruction//
CExecutable::CExecutable(vector <CToken> tokens){ m_tokens=tokens;}
CExecutable::~CExecutable(){ m_intArray.clear(); m_tokens.clear();}
void CExecutable::Run(void){ for(int i=0;i<=m_tokens.size()-1;i++)//注意:i是个十分重要的读取指针 { if(m_tokens.at(i).token_type==COMMAND) { switch(m_tokens.at(i).tok) file://tok表示是什么命令 { case PRINT: Run_Print(&i); break; case DIM: Run_Dim(&i); break; default: break; } } file://赋值语句一定要在最后来判断,因为这样如果是if后的条件判断就可以在 file://前面的if命令中跳过 if(*m_tokens.at(i).token=='=') file://如果是赋值语句 Run_Assignment(&i); }}
void CExecutable::Run_Print(int *index) file://*index是m_tokens里的指针{ if(*index<m_tokens.size()-1) // 如果下面还有token { if(m_tokens.at((*index)+1).token_type==ENTER) file://如果接下来是命令 { printf("/n"); return; } (*index)++; int token_type=m_tokens.at(*index).token_type; if(Isvar(m_tokens.at(*index).token)) file://如果接下来是变量 token_type=VARIABLE; switch(token_type) { case QUOTE: file://如果是要打印字符串 { printf(m_tokens.at(*index).token); return; } case VARIABLE: file://打印代数式 type只要不是COMMAND就是可以当代数式处理 case NUMBER: case DELIMITER: { int result; Ai_GetNextValue(&result,INTEGER,index); printf("%d",result); return; } default: printf("/n"); return; } } printf("/n"); }
void CExecutable::Run_Dim(int *index) file://~~{ int i=*index; if(i<m_tokens.size()-1)//~~ if(m_tokens.at(i+1).token_type==STRING) { if(i<m_tokens.size()-3) file://如果下面还应该有 变量名,As,类型 三个tokens { CintMember member; if(m_tokens.at(i+2).token_type==COMMAND && m_tokens.at(i+2).tok==AS) file://如果接下来的token是As { if(m_tokens.at(i+3).token_type==COMMAND)//接下来是变量类型 switch(m_tokens.at(i+3).tok) file://看看是什么变量类型 { case INTEGER: // 如果是Integer类型 strcpy(member.name,m_tokens.at(i+1).token); member.value=0; m_intArray.push_back(member); *index+=3; // 将m_tokens里的指针跳3个 break; default: break; } } } }}
void CExecutable::Run_Assignment(int *index) file://index必须指到'='的token{ int var_type=Isvar(m_tokens.at(*index - 1).token); if(!var_type) // 如果等号前面不是个变量 { serror(0); return; } switch(var_type) { case INTEGER: { int Var_No,value; if(!Ai_GetVarNo(m_tokens.at(*index-1).token,&Var_No,INTEGER)) break; (*index)++; if(!Ai_GetNextValue(&value,INTEGER,index)) break; m_intArray.at(Var_No).value=value; break; } default: break; }}
int CExecutable::Ai_GetNextValue(void *result,int type,int *index) file://index指到代数式的第一个token{ switch(type) { case INTEGER: get_exp((int*)result,index); return 1; default: return 0; }
}
int CExecutable::Ai_GetVarNo(char *name,int *result,int type){ switch(type) { case INTEGER: { if(m_intArray.size()==0) return 0; for(int i=0;i<=m_intArray.size()-1;i++) if(!strcmp(name,m_intArray.at(i).name)) *result=i; return 1; } default: return 0; }
}void CExecutable::get_exp(int *result,int *index){ if (!*m_tokens.at(*index).token) { serror(2); return; } level2(result,index); }
/* add or subtract two terms */void CExecutable::level2(int *result,int *index){ register char op; int hold; level3(result,index); while ((op = *m_tokens.at(*index).token) =='+' || op == '-') { (*index)++; level3(&hold,index); arith(op,result,&hold); }}
/* multiply or divide two factors */void CExecutable::level3(int *result,int *index){ register char op; int hold; level4(result,index); while ((op = *m_tokens.at(*index).token) == '*' || op == '/' || op == '%') { (*index)++; level3(&hold,index); arith(op,result,&hold); }}
/* process integer exponent */void CExecutable::level4(int *result,int *index){ register char op; int hold; level5(result,index); if ((op = *m_tokens.at(*index).token) == '^') { (*index)++; level5(&hold,index); arith(op,result,&hold); }}
/* is a unary + or - */ void CExecutable::level5(int *result,int *index){ register char op; op = 0; if ((m_tokens.at(*index).token_type==DELIMITER) && *m_tokens.at(*index).token == '+' || *m_tokens.at(*index).token == '-' ) { op = *m_tokens.at(*index).token; (*index)++; } level6(result,index); if (op) if(op=='-') *result=-(*result);}
/* process parenthesized expression */ void CExecutable::level6(int *result,int *index){ if ((*m_tokens.at(*index).token == '(') && (m_tokens.at(*index).token_type == DELIMITER)) { (*index)++; level2(result,index); if (*m_tokens.at(*index).token!=')') serror(1); (*index)++; } else primitive(result,index);}
/* find value of number or variable */void CExecutable::primitive(int *result,int *index){ int token_type=m_tokens.at(*index).token_type; if(Isvar(m_tokens.at(*index).token)) token_type=VARIABLE; switch (token_type) { case VARIABLE: find_var(m_tokens.at(*index).token,result); (*index)++; return; case NUMBER: *result = atoi(m_tokens.at(*index).token); (*index)++; return; default: serror(0); }}
int CExecutable::find_var(char *var_name,void *value){ for(int i=0;i<=m_intArray.size()-1;i++) if(!strcmp(var_name,m_intArray.at(i).name)) { int *int_value=(int *)value; *int_value=m_intArray.at(i).value; return 1; } return 0;}
int CExecutable::Isvar(char *name){ if(m_intArray.size()==0) return 0; for(int i=0;i<=m_intArray.size()-1;i++) if(!strcmp(name,m_intArray.at(i).name)) return INTEGER; return 0;}
/* perform the specified arithmetic */void CExecutable::arith(char o,int *r,int *h){ /*register*/ int t,ex; switch (o) { case '-': *r = *r-*h; break; case '+': *r = *r+*h; break; case '*': *r = *r**h; break; case '/': *r = (*r)/(*h); break; case '%': *r = (*r)%(*h); break; case '^': ex = *r; if (*h==0) { *r = 1; break; } for (t=*h-1;t>0;--t) *r=(*r)*ex; break; }}
int CExecutable::look_up(char *c){ if(strcmp(c,"print")==0) return PRINT; if(strcmp(c,"Integer")==0) return INTEGER; if(strcmp(c,"Dim")==0) return DIM; if(strcmp(c,"As")==0) return AS; return 0;}
void CExecutable::serror(int error){ char *e[] = { "syntax error", "unbalanced parentheses", "no expression present", "equal sign expected", "not a variable", "label table full", "duplicate label", "undefined label", "THEN expected", "TO expected", "too many nested FOR loops", "NEXT without FOR", "too many nested GOSUB", "RETURN without GOSUB" };
printf ("%s/n",e[error]);}