關於Basic程式直譯器及編譯原理的簡單化(2)---C++封裝好的Basic直譯器 (轉)
這是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
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
virtual ~CExecutable();
void Run();
private:
vector
vector
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
{
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(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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 自己動手寫basic直譯器 一
- 化繁為簡的翻譯機——直譯器模式模式
- 淺談彙編器、編譯器和直譯器編譯
- python直譯器的安裝Python
- 前端與編譯原理——用JS寫一個JS直譯器前端編譯原理JS
- 前端與編譯原理——用 JS 寫一個 JS 直譯器前端編譯原理JS
- 源語言、目標語言、翻譯器、編譯器、直譯器編譯
- Ipython 直譯器Python
- 什麼是Python全域性直譯器鎖(GIL)?全域性直譯器鎖的好處!Python
- 在C,C++,java和python執行時直譯器和編譯器的區別C++JavaPython編譯
- python直譯器在哪Python
- 直譯器模式(Interpreter)模式
- 極簡設計模式-直譯器模式設計模式
- 簡說設計模式——直譯器模式設計模式
- Python3 直譯器Python
- VScode和python直譯器VSCodePython
- 24_直譯器模式模式
- Python直譯器和IPythonPython
- Skywalking-07:OAL原理——直譯器實現
- C++編譯器優化C++編譯優化
- 設計模式(十五)直譯器設計模式
- Python直譯器有幾種Python
- cmd.exe直譯器漏洞
- Go編譯器簡介【譯】Go編譯
- 程式碼線上編譯器(上)- 編輯及編譯編譯
- Python教程分享:Python直譯器分類及版本Python
- python理論知識及python直譯器和pycharm安裝PythonPyCharm
- 設計模式之直譯器模式設計模式
- Python與全域性直譯器鎖Python
- Python直譯器分類有哪些?Python
- Python GIL(全域性直譯器鎖)Python
- 安裝c, c++編譯器 on AIXC++編譯AI
- 編譯原理——C++版桌面計算器編譯原理C++
- 關於支援OPenACC的編譯器說明編譯
- 【翻譯】ECMAScript裝飾器的簡單指南
- 編譯程式(compiler)的簡單分析編譯Compile
- Python 新提案:“廢除”全域性直譯器鎖 GIL | CPython 直譯器或許會變得更快Python
- 常見的Python五大直譯器!Python
- 全新的.NET直譯器 – Mono已經到來Mono