分享
 
 
 

关于Basic程序解释器及编译原理的简单化(2)---C++封装好的Basic解释器

王朝c/c++·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

这是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]);

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有