關於Basic程式直譯器及編譯原理的簡單化(2)---C++封裝好的Basic直譯器 (轉)

worldblog發表於2007-12-29
關於Basic程式直譯器及編譯原理的簡單化(2)---C++封裝好的Basic直譯器 (轉)[@more@]

這是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=='')
 {
 *m_token.token='';
 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]='';
 m_token.token_type=ENTER;
 prog++;
 return m_token;
 }
 if( isdelim(*prog)) // 如果找得到運算子號標記
 {
  *m_token.token=*prog;
  *(m_token.token+1)='';
  m_token.tok=0;
  m_token.token_type=DELIMITER;
  prog++;
  return m_token;  // 譬如 token[0]='+' token[1]='';
 }

 if(*prog=='"')  // 如果是字串
 {
 prog++;
 int i=0;
 while(*prog!='"' && *prog!='r')
 {
 m_token.token[i]=*prog;
 i++;
 prog++;
 }
 prog++;
 m_token.token[i]='';
 m_token.token_type=QUOTE;
 return m_token;
 }

 if( isdigit(*prog)) // 如果找到數字標記
 {
 int i=0;
 while(isdigit(*prog) && i {
 m_token.token[i]=*prog;
 i++;
 prog++;
 }
 m_token.token[i]='';
 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]='';
 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 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 tokens);
 virtual ~CExecutable();
 void Run();
private:
 vector m_tokens; 所有標記的
 vector m_intArray; 所有int型別的變數
 void Run_Print(int *index); index是重要的m_tokens裡的指標
 void Run_Dim(int *index);
 void Run_Assignment(int *index);// 賦值語句
 是輔助的意思,Ai_*()是輔助
 int Ai_GetNextValue(void* result,int type,int *index); 到代數式的值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 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) 表示是什麼命令
  {
  case PRINT: Run_Print(&i);
  break;
  case DIM:  Run_Dim(&i);
  break;
  default:  break;
  }
  }
  值語句一定要在最後來判斷,因為這樣如果是if後的條件判斷就可以在
  面的if命令中跳過
  if(*m_tokens.at(i).token=='=') 果是賦值語句
  Run_Assignment(&i);
  }
}

void CExecutable::Run_Print(int *index) index是m_tokens裡的指標
{
 if(*index { 
 if(m_tokens.at((*index)+1).token_type==ENTER) 果接下來是命令
 {
 printf("n");
 return;
 }
 (*index)++; 
 int token_type=m_tokens.at(*index).token_type;
 if(Isvar(m_tokens.at(*index).token)) 果接下來是變數
 token_type=VARIABLE;
 
 switch(token_type)
 {
 case QUOTE: 果是要列印字串
 {
 printf(m_tokens.at(*index).token);
 return;
 }
 case VARIABLE:  印代數式 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)
{
 int i=*index;
 if(i  if(m_tokens.at(i+1).token_type==STRING)
  {
  if(i  {
  CintMember member;
  if(m_tokens.at(i+2).token_type==COMMAND &&
  m_tokens.at(i+2).tok==AS) 果接下來的token是As
  {
 if(m_tokens.at(i+3).token_type==COMMAND)//接下來是變數型別
  switch(m_tokens.at(i+3).tok) 看是什麼變數型別
  {
  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) 必須指到'='的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) 指到代數式的第一個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 div 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;
}

/* perfothe 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 ls",
  "NEXT without FOR",
  "too many nested GOSUB",
  "RETURN without GOSUB"
  };

  printf ("%sn",e[error]);
}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-996095/,如需轉載,請註明出處,否則將追究法律責任。

相關文章