易码技术论坛

 找回密码
 加入易码
搜索
查看: 82542|回复: 1

[教程] [分享]Basic程序解释器及编译原理的简单化

[复制链接]
发表于 2005-11-8 15:22:00 | 显示全部楼层
这是CMake的源代码.主要负责词汇的提取
你可以调用它的CMake::get_token(),返回个CToken的类.
  1. /////////////////////////////////////////////////////
  2. // Make.h
  3. ///////////////////////////////////////////////////

  4. enum token_types{DELIMITER,VARIABLE,NUMBER,COMMAND,
  5.              STRING,QUOTE,FINISHED,NONE,ENTER};         // 标记类型集合


  6. #define TOKEN_MAX 80
  7. #define STRDELIMITER "+-*^/=;(),><" // 符号集合
  8. #define DIM     11 // Dim
  9. #define AS      12 // As
  10. #define INTEGER 13 // Integer
  11. #define PRINT   14 // Print

  12. class CToken
  13. {
  14. public:
  15. char token[TOKEN_MAX];
  16. int token_type;
  17. int tok;
  18. };

  19. class CMake  
  20. {
  21. public:
  22. CMake(char *Prog,int Proglength);
  23. virtual ~CMake();
  24. public:
  25.     char *prog;
  26. int proglength;
  27. int isdelim(char c);     // 如果是运算符号返回1,不是则返回0
  28. int iswhite(char c);     // 是空格返回1,不是则返回0
  29. int look_up(char *c);    // 返回COMMAND类型,c是COMMAND字符串的指针
  30. CToken get_token(void);   // 得到标记
  31. int findchar(char *str,char ch); // 从str里找到ch,返回其在str里的引索;如果str里没有ch,则返回-1
  32. };

  33. /////////////////////////////////////////////////////////////////////





  34. // Make.cpp: implementation of the CMake class.
  35. //
  36. //////////////////////////////////////////////////////////////////////

  37. #include "stdafx.h"
  38. #include "Make.h"

  39. //////////////////////////////////////////////////////////////////////
  40. // Construction/Destruction
  41. //////////////////////////////////////////////////////////////////////

  42. CMake::CMake(char *Prog,int Proglength)
  43. {
  44.   proglength=Proglength;
  45.   prog=new char[Proglength+1];
  46.   strcpy(prog,Prog);
  47. }

  48. CMake::~CMake()
  49. {

  50. }


  51. CToken CMake::get_token(void)
  52. {
  53. register char *temp;
  54. CToken m_token;
  55.     m_token.token_type=0;
  56. m_token.tok=0;
  57. temp=m_token.token;
  58. if(*prog=='\0')
  59. {
  60.   *m_token.token='\0';
  61.   m_token.tok=0;
  62.   m_token.token_type=FINISHED;
  63.   return m_token;
  64. }
  65. while(iswhite(*prog)) ++prog;
  66.    
  67. if(*prog=='\r') // 如果是换行符
  68. {
  69.   m_token.token[0]=*prog;
  70.   m_token.token[1]='\0';
  71.   m_token.token_type=ENTER;
  72.   prog++;
  73.   return m_token;
  74. }
  75. if( isdelim(*prog)) // 如果找得到运算符号标记
  76. {
  77.     *m_token.token=*prog;
  78.     *(m_token.token+1)='\0';
  79.     m_token.tok=0;
  80.     m_token.token_type=DELIMITER;
  81.     prog++;
  82.     return m_token;            // 譬如 token[0]='+' token[1]='\0';
  83. }

  84. if(*prog=='"')   // 如果是字符串
  85. {
  86.   prog++;
  87.   int i=0;
  88.   while(*prog!='"' && *prog!='\r')
  89.   {
  90.    m_token.token[i]=*prog;
  91.    i++;
  92.    prog++;
  93.   }
  94.   prog++;
  95.   m_token.token[i]='\0';
  96.   m_token.token_type=QUOTE;
  97.   return m_token;
  98. }

  99. if( isdigit(*prog)) // 如果找到数字标记
  100. {
  101.   int i=0;
  102.   while(isdigit(*prog) && i<TOKEN_MAX) // 小于token最长为80个字符
  103.   {
  104.    m_token.token[i]=*prog;
  105.    i++;
  106.    prog++;
  107.   }
  108.   m_token.token[i]='\0';
  109.   m_token.token_type=NUMBER;
  110.   return m_token;
  111. }
  112. if( isalpha(*prog)) // 如果是命令COMMAND或是一般标记STRING
  113. {
  114.   int i=0;
  115.   while(!isdelim(*prog) && *prog!=' ') // 不能是运算符号和空格
  116.   {
  117.    m_token.token[i]=*prog;
  118.    i++;
  119.    prog++;
  120.   }
  121.   m_token.token[i]='\0';
  122.   if(look_up(m_token.token)) // 如果能查到它是命令COMMAND
  123.   {
  124.    m_token.token_type=COMMAND;
  125.    m_token.tok=look_up(m_token.token);
  126.   }
  127.   else
  128.   {
  129.    m_token.token_type=STRING;
  130.   }
  131.   return m_token;
  132. }


  133. m_token.token_type=NONE;
  134. prog++;
  135. return m_token;
  136. }

  137. int CMake::iswhite(char c)
  138. {
  139. if(c==' '||c=='\t') return 1;
  140. else return 0;
  141. }

  142. int CMake::isdelim(char c)
  143. {
  144. if( findchar(STRDELIMITER,*prog) >= 0 || c==9 || c=='\r' || c==0)
  145.   return 1;
  146. return 0;
  147. }

  148. int CMake::findchar(char *str,char ch)
  149. {
  150. int length=strlen(str);
  151. if(length>0)
  152. {
  153.   for(int i=0;i<length;i++)
  154.    if(str[i]==ch)
  155.       return i;
  156.    return -1;
  157. }
  158. else return -1;
  159. }

  160. int CMake::look_up(char *c)
  161. {
  162. if(strcmp(c,"print")==0)
  163.   return PRINT;
  164.     if(strcmp(c,"Integer")==0)
  165.   return INTEGER;
  166. if(strcmp(c,"Dim")==0)
  167.   return DIM;
  168. if(strcmp(c,"As")==0)
  169.   return AS;

  170.     return 0;
  171. }

  172. 这是执行代码的CExecutable封装

  173. //////////////////////////////////////////////////
  174. // CExecutable.h
  175. ////////////////////////////////////////////////

  176. class CintMember
  177. {
  178. public:
  179. char name[64];
  180. int value;
  181. };

  182. class CExecutable  
  183. {
  184. public:
  185. CExecutable(vector <CToken> tokens);
  186. virtual ~CExecutable();
  187. void Run();
  188. private:
  189. vector <CToken> m_tokens; [url]file://装[/url]所有标记的数据库
  190. vector <CintMember> m_intArray; [url]file://装[/url]所有int类型的变量
  191. void Run_Print(int *index); [url]file://*[/url]index是重要的m_tokens里的指针
  192. void Run_Dim(int *index); [url]file://~~[/url]
  193. void Run_Assignment(int *index);// 赋值语句
  194. [url]file://Ai[/url]是辅助的意思,Ai_*()是辅助函数
  195. int Ai_GetNextValue(void* result,int type,int *index); [url]file://得[/url]到代数式的值result
  196. int Ai_GetVarNo(char *name,int *result,int type);//得到变量在Array中的引索result
  197. void get_exp(int *result,int *index);
  198. void level2(int *result,int *index);
  199. void level3(int *result,int *index);
  200. void level4(int *result,int *index);
  201. void level5(int *result,int *index);
  202.     void level6(int *result,int *index);
  203. void primitive(int *result,int *index);
  204. void arith(char o,int *r,int *h);
  205. void serror(int error);
  206. int look_up(char *c);
  207. int find_var(char *var_name,void *value); // 查找变量,将变量值装在*value
  208. int Isvar(char *name); // 看name是否是变量,返回变量类型 0:什么都不是,1:Integer,2:string
  209. };


  210. /////////////////////////////////////////

  211. // Executable.cpp: implementation of the CExecutable class.
  212. //
  213. //////////////////////////////////////////////////////////////////////

  214. #include "stdafx.h"
  215. #include "Executable.h"

  216. //////////////////////////////////////////////////////////////////////
  217. // Construction/Destruction
  218. //////////////////////////////////////////////////////////////////////

  219. CExecutable::CExecutable(vector <CToken> tokens)
  220. {
  221. m_tokens=tokens;
  222. }

  223. CExecutable::~CExecutable()
  224. {
  225. m_intArray.clear();
  226. m_tokens.clear();
  227. }

  228. void CExecutable::Run(void)
  229. {
  230.    for(int i=0;i<=m_tokens.size()-1;i++)//注意:i是个十分重要的读取指针
  231.    {
  232.   if(m_tokens.at(i).token_type==COMMAND)
  233.   {
  234.    switch(m_tokens.at(i).tok) [url]file://tok[/url]表示是什么命令
  235.    {
  236.    case PRINT: Run_Print(&i);
  237.          break;
  238.    case DIM:   Run_Dim(&i);
  239.             break;
  240.    default:   break;
  241.    }
  242.   }
  243.   [url]file://赋[/url]值语句一定要在最后来判断,因为这样如果是if后的条件判断就可以在
  244.   [url]file://前[/url]面的if命令中跳过
  245.   if(*m_tokens.at(i).token=='=') [url]file://如[/url]果是赋值语句
  246.    Run_Assignment(&i);
  247.    }
  248. }

  249. void CExecutable::Run_Print(int *index) [url]file://*[/url]index是m_tokens里的指针
  250. {
  251. if(*index<m_tokens.size()-1) // 如果下面还有token
  252. {   
  253.   if(m_tokens.at((*index)+1).token_type==ENTER) [url]file://如[/url]果接下来是命令
  254.   {
  255.    printf("\n");
  256.    return;
  257.   }
  258.   (*index)++;   
  259.   int token_type=m_tokens.at(*index).token_type;
  260.   if(Isvar(m_tokens.at(*index).token)) [url]file://如[/url]果接下来是变量
  261.    token_type=VARIABLE;
  262.         
  263.   switch(token_type)
  264.   {
  265.   case QUOTE: [url]file://如[/url]果是要打印字符串
  266.    {
  267.     printf(m_tokens.at(*index).token);
  268.     return;
  269.    }
  270.   case VARIABLE:  [url]file://打[/url]印代数式 type只要不是COMMAND就是可以当代数式处理
  271.   case NUMBER:
  272.   case DELIMITER:     
  273.    {
  274.     int result;
  275.           Ai_GetNextValue(&result,INTEGER,index);
  276.     printf("%d",result);
  277.     return;
  278.    }
  279.   default: printf("\n");
  280.      return;
  281.   }
  282. }
  283. printf("\n");

  284. }

  285. void CExecutable::Run_Dim(int *index) [url]file://~~[/url]
  286. {
  287. int i=*index;
  288. if(i<m_tokens.size()-1)//~~
  289.   if(m_tokens.at(i+1).token_type==STRING)
  290.   {
  291.    if(i<m_tokens.size()-3) [url]file://如[/url]果下面还应该有 变量名,As,类型 三个tokens
  292.    {
  293.     CintMember member;
  294.     if(m_tokens.at(i+2).token_type==COMMAND &&
  295.      m_tokens.at(i+2).tok==AS) [url]file://如[/url]果接下来的token是As
  296.     {
  297.     if(m_tokens.at(i+3).token_type==COMMAND)//接下来是变量类型
  298.      switch(m_tokens.at(i+3).tok) [url]file://看[/url]看是什么变量类型
  299.      {
  300.           case INTEGER: // 如果是Integer类型
  301.         strcpy(member.name,m_tokens.at(i+1).token);
  302.         member.value=0;
  303.         m_intArray.push_back(member);
  304.         *index+=3; // 将m_tokens里的指针跳3个
  305.         break;
  306.           default:     
  307.         break;
  308.      }
  309.     }
  310.    }
  311.   }
  312. }

  313. void CExecutable::Run_Assignment(int *index) [url]file://index[/url]必须指到'='的token
  314. {
  315. int var_type=Isvar(m_tokens.at(*index - 1).token);
  316. if(!var_type) // 如果等号前面不是个变量
  317. {
  318.   serror(0);
  319.   return;
  320. }
  321. switch(var_type)
  322. {
  323. case INTEGER:
  324.   {
  325.    int Var_No,value;
  326.    if(!Ai_GetVarNo(m_tokens.at(*index-1).token,&Var_No,INTEGER))
  327.                break;
  328.    (*index)++;
  329.             if(!Ai_GetNextValue(&value,INTEGER,index))
  330.       break;
  331.    m_intArray.at(Var_No).value=value;
  332.    break;
  333.   }
  334. default: break;
  335. }
  336. }



  337. int CExecutable::Ai_GetNextValue(void *result,int type,int *index) [url]file://index[/url]指到代数式的第一个token
  338. {
  339. switch(type)
  340. {
  341. case INTEGER: get_exp((int*)result,index);
  342.             return 1;
  343. default:    return 0;
  344. }

  345. }

  346. int CExecutable::Ai_GetVarNo(char *name,int *result,int type)
  347. {
  348. switch(type)
  349. {
  350. case INTEGER:
  351.   {
  352.    if(m_intArray.size()==0)
  353.     return 0;
  354.    for(int i=0;i<=m_intArray.size()-1;i++)
  355.     if(!strcmp(name,m_intArray.at(i).name))
  356.      *result=i;
  357.     return 1;
  358.   }
  359. default: return 0;
  360. }

  361. }
  362. void CExecutable::get_exp(int *result,int *index)
  363. {
  364.     if (!*m_tokens.at(*index).token)
  365. {
  366.         serror(2);
  367.         return;
  368.     }
  369.     level2(result,index);
  370.    
  371. }


  372. /* add or subtract two terms */
  373. void CExecutable::level2(int *result,int *index)
  374. {
  375.     register char op;
  376.     int hold;
  377.     level3(result,index);
  378.     while ((op = *m_tokens.at(*index).token) =='+' || op == '-')  
  379. {
  380.         (*index)++;
  381.         level3(&hold,index);
  382.         arith(op,result,&hold);
  383.     }
  384. }


  385. /* multiply or divide two factors */
  386. void CExecutable::level3(int *result,int *index)
  387. {
  388. register char op;
  389.     int hold;
  390.     level4(result,index);
  391.     while ((op = *m_tokens.at(*index).token) == '*' || op == '/' || op == '%')  
  392. {
  393.         (*index)++;
  394.         level3(&hold,index);
  395.         arith(op,result,&hold);
  396.     }
  397. }


  398. /* process integer exponent */
  399. void CExecutable::level4(int *result,int *index)
  400. {
  401. register char op;
  402.     int hold;
  403.     level5(result,index);
  404.     if ((op = *m_tokens.at(*index).token) == '^')
  405. {
  406.         (*index)++;
  407.         level5(&hold,index);
  408.         arith(op,result,&hold);
  409.     }
  410. }
  411.               

  412. /* is a unary + or - */              
  413. void CExecutable::level5(int *result,int *index)
  414. {
  415.     register char op;
  416.     op = 0;
  417.     if ((m_tokens.at(*index).token_type==DELIMITER) &&
  418.   *m_tokens.at(*index).token == '+' ||
  419.   *m_tokens.at(*index).token == '-' )  
  420. {
  421.         op = *m_tokens.at(*index).token;
  422.         (*index)++;
  423.     }
  424.     level6(result,index);
  425.     if (op)  
  426.   if(op=='-')
  427.    *result=-(*result);
  428. }
  429.                

  430. /* process parenthesized expression */               
  431. void CExecutable::level6(int *result,int *index)
  432. {
  433. if ((*m_tokens.at(*index).token == '(') && (m_tokens.at(*index).token_type == DELIMITER))  
  434. {
  435.         (*index)++;
  436.         level2(result,index);
  437.         if (*m_tokens.at(*index).token!=')')
  438.             serror(1);
  439.         (*index)++;
  440.     }
  441.     else
  442.         primitive(result,index);
  443. }

  444. /* find value of number or variable */
  445. void CExecutable::primitive(int *result,int *index)
  446. {
  447. int token_type=m_tokens.at(*index).token_type;
  448.     if(Isvar(m_tokens.at(*index).token))  
  449.   token_type=VARIABLE;
  450.     switch (token_type)  {
  451.         case VARIABLE:
  452.             find_var(m_tokens.at(*index).token,result);
  453.             (*index)++;
  454.             return;
  455.         case NUMBER:
  456.             *result = atoi(m_tokens.at(*index).token);
  457.             (*index)++;
  458.             return;
  459.         default:
  460.             serror(0);
  461.     }
  462. }

  463. int CExecutable::find_var(char *var_name,void *value)
  464. {
  465. for(int i=0;i<=m_intArray.size()-1;i++)
  466.   if(!strcmp(var_name,m_intArray.at(i).name))
  467.   {
  468.    int *int_value=(int *)value;
  469.    *int_value=m_intArray.at(i).value;
  470.    return 1;
  471.   }
  472.     return 0;
  473. }

  474. int CExecutable::Isvar(char *name)
  475. {
  476. if(m_intArray.size()==0)
  477.   return 0;
  478. for(int i=0;i<=m_intArray.size()-1;i++)
  479.   if(!strcmp(name,m_intArray.at(i).name))
  480.         return INTEGER;
  481. return 0;
  482. }

  483. /* perform the specified arithmetic */
  484. void CExecutable::arith(char o,int *r,int *h)
  485. {
  486.     /*register*/ int t,ex;
  487.    
  488.     switch (o)  {
  489.         case '-':
  490.             *r = *r-*h;
  491.             break;
  492.         case '+':
  493.             *r = *r+*h;
  494.             break;
  495.         case '*':
  496.             *r = *r**h;
  497.             break;
  498.         case '/':
  499.             *r = (*r)/(*h);
  500.             break;
  501.         case '%':
  502.             *r = (*r)%(*h);
  503.             break;
  504.         case '^':
  505.             ex = *r;
  506.             if (*h==0)  {
  507.                 *r = 1;
  508.                 break;
  509.             }
  510.             for (t=*h-1;t>0;--t)  *r=(*r)*ex;
  511.             break;
  512.     }
  513. }

  514. int CExecutable::look_up(char *c)
  515. {
  516. if(strcmp(c,"print")==0)
  517.   return PRINT;
  518.     if(strcmp(c,"Integer")==0)
  519.   return INTEGER;
  520. if(strcmp(c,"Dim")==0)
  521.   return DIM;
  522. if(strcmp(c,"As")==0)
  523.   return AS;
  524.     return 0;
  525. }

  526. void CExecutable::serror(int error)
  527. {
  528. char *e[] = {
  529.         "syntax error",
  530.         "unbalanced parentheses",
  531.         "no expression present",
  532.         "equal sign expected",
  533.         "not a variable",
  534.         "label table full",
  535.         "duplicate label",
  536.         "undefined label",
  537.         "THEN expected",
  538.         "TO expected",
  539.         "too many nested FOR loops",
  540.         "NEXT without FOR",
  541.         "too many nested GOSUB",
  542.         "RETURN without GOSUB"
  543.     };

  544.     printf ("%s\n",e[error]);
  545. }
复制代码
 楼主| 发表于 2005-11-8 15:21:24 | 显示全部楼层 |阅读模式
在网上,看到还是有部分程序爱好者希望能编出自己的编译器.当然,这的确是件难事,许多人都说要去看什么编译原理和精通汇编语言,结果让这些爱好者都望而却步.但是,当我们亲手去做做后,发现要做一个简单的程序解释器(就像Java和Basic)那样,还是挺容易的.你根本不用去看那些东西,只要你懂C语言,在看了本文后,就可以完成那样的解释器.

在网上,有许多大型C语言,Perl语言的编译器源代码.但当你下载后看看,竟发现点都看不懂.其实那些东西还是不看为妙.看了本文后,我相信你宁愿自己动手编,也不愿意去领会那些庞大的源代码了.

少说费话了,我们开始讲解.

这一篇Basic解释器的代码.十分经典.而且十分简单化.

get_token()是词汇提取,譬如 PRINT A+B

通过调用一次get_token(),就在 字符串token里装上PRINT
再调用一次get_token(),token里就装上A
再调用一次get_token(),token里就装上+
再调用一次get_token(),token里就装上B

很简单吧!

putback()是将prog指针向回移动一格.其中包含了词发分析和十分关键的代数式求值get_exp(int *result)

关于它的代数式求值get_exp(int *result),用到递归函数

void get_exp(),level2(),level3(),level4(),level5();
void level6(),primitive(),arith(),unary();

,确实难看懂,不过你尽管拿来用就是了.

话不多说,你看源代码就是了.最后,我将给你看看C++中完整的源代码
  1. /*
  2.    recursive descent parser for integer expression
  3.    which may include variables
  4. */

  5. #include <STDIO.H>
  6. #include <SETJMP.H>
  7. #include <MATH.H>
  8. #include <CTYPE.H>
  9. #include <STDLIB.H>

  10. #define DELIMITER 1
  11. #define VARIABLE 2
  12. #define NUMBER 3
  13. #define COMMAND 4
  14. #define STRING 5
  15. #define QUOTE 6

  16. #define EOL 9
  17. #define FINISHED 10

  18. extern char *prog;  /* holds expression to be analyzed */

  19. extern jmp_buf e_buf;  /* hold enviroment */
  20. extern int variables[26];  /* variables */
  21. extern struct commands {
  22.     char command[20];
  23.     char tok;
  24. } table[];

  25. extern char token[80];  /* holds string representation of token */
  26. extern char token_type;  /* contains type of token */
  27. extern char tok;  /* holds the internal representation of token */

  28. void get_exp(),level2(),level3(),level4(),level5();
  29. void level6(),primitive(),arith(),unary();
  30. void serror(),putback();


  31. /* entry point into parser */
  32. void get_exp(int *result)
  33. {
  34.     get_token();
  35.     if (!*token) {
  36.         serror(2);
  37.         return;
  38.     }
  39.     level2(result);
  40.     putback();  /*return last token read to input stream */
  41. }


  42. /* add or subtract two terms */
  43. void level2(int *result)
  44. {
  45.     register char op;
  46.     int hold;

  47.     level3(result);
  48.     while ((op = *token) =='+' || op == '-')  {
  49.         get_token();
  50.         level3(&hold);
  51.         arith(op,result,&hold);
  52.     }
  53. }


  54. /* multiply or divide two factors */
  55. void level3(int *result)
  56. {
  57.     register char op;
  58.     int hold;

  59.     level4(result);
  60.     while ((op = *token) == '*' || op == '/' || op == '%')  {
  61.         get_token();
  62.         level3(&hold);
  63.         arith(op,result,&hold);
  64.     }
  65. }


  66. /* process integer exponent */
  67. void level4(int *result)
  68. {
  69.     register char op;
  70.     int hold;

  71.     level5(result);
  72.     if (*token == '^') {
  73.         get_token();
  74.         level4(&hold);
  75.         arith(op,result,&hold);
  76.     }
  77. }


  78. /* is a unary + or - */
  79. void level5(int *result)
  80. {
  81.     register char op;

  82.     op = 0;
  83.     if ((token_type==DELIMITER) && *token == '+' || *token == '-' )  {
  84.         op = *token;
  85.         get_token();
  86.     }
  87.     level6(result);
  88.     if (op)  unary(op,result);
  89. }


  90. /* process parenthesized expression */
  91. void level6(int *result)
  92. {
  93.     if ((*token == '(') && (token_type == DELIMITER))  {
  94.         get_token();
  95.         level2(result);
  96.         if (*token!=')')
  97.             serror(1);
  98.         get_token();
  99.     }
  100.     else
  101.         primitive(result);
  102. }


  103. /* find value of number or variable */
  104. void primitive(int *result)
  105. {
  106.     switch (token_type)  {
  107.         case VARIABLE:
  108.             *result = find_var(token);
  109.             get_token();
  110.             return;
  111.         case NUMBER:
  112.             *result = atoi(token);
  113.             get_token();
  114.             return;
  115.         default:
  116.             serror(0);
  117.     }
  118. }


  119. /* perform the specified arithmetic */
  120. void arith(char o,int *r,int *h)
  121. {
  122.     register int t,ex;

  123.     switch (o)  {
  124.         case '-':
  125.             *r = *r-*h;
  126.             break;
  127.         case '+':
  128.             *r = *r+*h;
  129.             break;
  130.         case '*':
  131.             *r = *r**h;
  132.             break;
  133.         case '/':
  134.             *r = (*r)/(*h);
  135.             break;
  136.         case '%':
  137.             *r = (*r)%(*h);
  138.             break;
  139.         case '^':
  140.             ex = *r;
  141.             if (*h==0)  {
  142.                 *r = 1;
  143.                 break;
  144.             }
  145.             for (t=*h-1;t>0;--t)  *r=(*r)*ex;
  146.             break;
  147.     }
  148. }


  149. /* reverse the sign */
  150. void unary(char o,int *r)
  151. {
  152.     if (o=='-')  *r = -(*r);
  153. }


  154. /* find the value of a variable */
  155. int find_var(char *s)
  156. {
  157.     if (!isalpha(*s))  {
  158.         serror(4);  /* not a variable */
  159.         return 0;
  160.     }
  161.     return variables[toupper(*token)-'A'];
  162. }


  163. /* display an error message */
  164. void serror(int error)
  165. {
  166.     char *e[] = {
  167.         "syntax error",
  168.         "unbalanced parentheses",
  169.         "no expression present",
  170.         "equal sign expected",
  171.         "not a variable",
  172.         "label table full",
  173.         "duplicate label",
  174.         "undefined label",
  175.         "THEN expected",
  176.         "TO expected",
  177.         "too many nested FOR loops",
  178.         "NEXT without FOR",
  179.         "too many nested GOSUB",
  180.         "RETURN without GOSUB"
  181.     };

  182.     printf ("%s\n",e[error]);
  183.     longjmp(e_buf,1);  /* return to save point */
  184. }


  185. /* get a token */
  186. get_token()
  187. {
  188.     register char *temp;

  189.     token_type = 0;tok = 0;
  190.     temp = token;

  191.     if (*prog == '\0')  {   /* end of file */
  192.         *token = 0;
  193.         tok = FINISHED;
  194.         return (token_type = DELIMITER);
  195.     }

  196.     while (iswhite(*prog))  ++prog;  /* skip over white space */

  197.     if (*prog == '\r')  {   /* CR LF */
  198.         ++prog;++prog;
  199.         tok = EOL;*token = '\r';
  200.         token[1] = '\n';token[2] = 0;
  201.         return (token_type = DELIMITER);
  202.     }

  203.     if (strchr("+-*^/%=;(),><",*prog))  {  /* delimiter */
  204.         *temp = *prog;
  205.         prog++;  /* advance to next position */
  206.         temp++;
  207.         *temp=0;
  208.         return (token_type = DELIMITER);
  209.     }

  210.     if (*prog == '"')  {   /* quote string */
  211.         prog++;
  212.         while (*prog!='"'&&*prog!='\r')  *temp++=*prog++;
  213.         if (*prog=='\r')  serror(1);
  214.         prog++;*temp=0;
  215.         return (token_type = QUOTE);
  216.     }

  217.     if (isdigit(*prog))  {   /* number */
  218.         while (!isdelim(*prog))  *temp++=*prog++;
  219.         *temp = '\0';
  220.         return (token_type = NUMBER);
  221.     }

  222.     if (isalpha(*prog))  {   /* var or command */
  223.         while (!isdelim(*prog))  *temp++=*prog++;
  224.         token_type = STRING;
  225.     }

  226.     *temp = '\0';

  227.     /* see if a string is a command or a variable */
  228.     if (token_type == STRING)  {
  229.         tok = look_up(token);  /* convert to internal rep */
  230.         if (!tok)  token_type = VARIABLE;
  231.         else token_type = COMMAND;  /* is a command */
  232.     }
  233.     return token_type;
  234. }


  235. /* return a token to input stream */
  236. void putback()
  237. {
  238.     char *t;
  239.     t = token;
  240.     for (;*t;t++)  prog--;
  241. }


  242. look_up(char *s)
  243. {
  244.     register int i,j;
  245.     char *p;

  246.     /* convert to lowercase */
  247.     p = s;
  248.     while (*p)  { *p = tolower(*p); p++;  }

  249.     /* see if token is in table */
  250.     for (i=0;*table[i].command;i++)
  251.         if (!strcmp(table[i].command,s))  return table[i].tok;
  252.     return 0;   /* unknown command */
  253. }


  254. /* return true if c is a delimiter */
  255. isdelim(char c)
  256. {
  257.     if (strchr(";,+-<>/*%^=() ",c)||c==9||c=='\r'||c==0)
  258.         return 1;
  259.     return 0;
  260. }


  261. iswhite (char c)
  262. {
  263.     if (c==' '||c=='\t')  return 1;
  264.     else return 0;
  265. }
复制代码
发表于 2009-7-25 23:51:13 | 显示全部楼层
对我来说,真的很难懂
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-4-19 07:02 , Processed in 0.010434 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表