⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tokenoper_c.cpp

📁 MCS51单片机的宏汇编器源程序。有需要的朋友请下载!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------
//  TokenOper_C.cpp
//---------------------------------------------------------------------------
#include "JsGlobal_H.h"
#include "TokenOper_H.h"

//---------------------------------------------------------------------------
//
// 下面是与Tokenfield有关的操作的函数定义.
//
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 注意: 是 pt->next !! pt不能为空.
// 判断pt->next是否操作数,是则把它转为OPadToken, 即令pt->next=OPadToken.
// 正确返回0. 错误返回出错码err。
// 如果操作数个数为0, 返回的err为ExpNULLErr.
// err = ExpNULLErr, MissRtErr, MissLtErr, ExpSyrErr, MissEleErr
//---------------------------------------------------------------------------
inline ERR TokenOper::OPadToPack(Tokenfield* pt)
{ ERR err = OK_no_Err;
  int8 len = FetchOpadLen(pt, err);
  if( !err )       // 如果pt->next是操作数
   { OPadToToken(pt, len); } // 转为OPadToken
  return err;
} // end OPadToPack
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 对pt->next进行语法分析. 注意: 是 pt->next !! pt不能为空.
// 判断pt->next是否表达式,是则把它归约为ExpToken, 即令pt->next=ExpToken.
// pt->ExpPt 指向原来的表达式Token.
// 正确返回0. 错误返回出错码err。
// err = ExpNULLErr, MissRtErr, MissLtErr, ExpSyrErr, MissEleErr
//---------------------------------------------------------------------------
inline ERR TokenOper::ExpToPack(Tokenfield* pt)
{ ERR err = OK_no_Err;
  Tokenfield* pp = pt->next; // 创建临时变量pp
  int8u len = FetchExpLen(pp, err);      // 临时变量pp被丢弃, 返回err.
  // Now, len 装有表达式个数. err 装有错误号.
  if( !err )                 // 如果pt->next是表达式, len > 0
   { ExpToToken(pt,len); }  // 归约为ExpToken, 封装ExpToken包.成功返回.
  // Now, len == 0. 表示有错!
  return err;
} // end ExpToPack
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// 把以pt所指的结点开头的Token表删除。
//---------------------------------------------------------------------------
void TokenOper::DelTokenList(Tokenfield* &pt)
{ while(pt)
   { register Tokenfield* temp = pt->next;
     delete pt;
     pt = temp;
   } // end while
  // 最后pt==NULL。
} // end DelTokenList
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
// pt指向Operand头。 pt->OperandsList("#+Expr")
// 把pt所指的OPerand表达式(#+Expr)删除。
// pt不能为空! pt->ExpPt也不能为空!
//---------------------------------------------------------------------------
void TokenOper::DelOPNDTkn(Tokenfield* pt)
{ while(pt)
   { register Tokenfield* temp = pt->next;
     if(pt->Token == ExpresnKn)
      { DelTokenList(pt->ExpPt); } // endif
     delete pt;
     pt = temp;
   } // end while
  // 最后pt==NULL。
} // end DelOPNDTkn
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// pt->Token==Operand
// 把以pt所指的结点开头的Operand表(必须全都是Operand)删除。
//---------------------------------------------------------------------------
void TokenOper::DelOPNDList(Tokenfield* pt)
{ while(pt)
   { register Tokenfield* temp = pt->next;
     DelOPNDTkn(pt->ExpPt); // 把pt所指的下层OPerand表达式(#+Expr)删除。
     delete pt;
     pt = temp;
   } // end while
  // 最后pt==NULL。
} // end DelOPNDList
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// 注意: 是 pt->next !! pt不能为空.
// 把pt->next所指的Token为起点, 长度为len的一个表达式封装为表达式包(ExpToken).
// 其 ExpPt 域指向表达式。
// 要特别注意的是,len!=0,也不要超长(视乎该表达式的实际长度而定),否则程序崩溃!!
// 在使用完ExpToken后,要释放节点!
//---------------------------------------------------------------------------
void TokenOper::ExpToToken(Tokenfield* pt, int8u len)
{ Tokenfield* ExpNode = new Tokenfield;
  ExpNode->Token = ExpresnKn;
  ExpNode->ExpPt = pt->next;    // 创建一棵子树。
  pt->next = ExpNode;
  for( pt = ExpNode->ExpPt; len > 1; len-- ) { pt = pt->next; } // end for
  // Now, pt 移到表达式尾部。
  ExpNode->next = pt->next;
  pt->next = NULL;
} // end ExpToToken
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 注意: 是 pt->next !! pt不能为空.
// 把pt->next所指的Token为起点、长度为len的操作数封装为操作数包,成为OPadToken.
// 其 ExpPt 域指向表达式。
// 要特别注意的是,len!=0, 也不要超长,否则程序崩溃!!
// 在使用完OPadToken后,要释放节点!
//---------------------------------------------------------------------------
void TokenOper::OPadToToken(Tokenfield* pt, int8u len)
{ Tokenfield* Node = new Tokenfield;
  Node->Token = OperandKn;   // 归约成OperandKn Token.
  Node->ExpPt = pt->next;    // 创建一棵子树。
  pt->next = Node;
  for( pt = Node->ExpPt; len > 1; len-- ) { pt = pt->next; } // end for
  // Now, pt 移到表达式尾部。
  Node->next = pt->next;
  pt->next = NULL;
} // end OPadToToken
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 判断p指向的结点是否为一个表达式,返回表达式长度len. 如果正确, len>0.
// 不是一个表达式,返回len=0, 并令err带错误号返回.
// 调用后, 如果正确,p被修改. p指向表达式的下一个Token。
// 如果有错,p指向有错的Token,err存有错误信息。    (说明:0<=len<=255)
// err = ExpNULLErr, MissRtErr, MissLtErr, ExpSyrErr, MissEleErr
//---------------------------------------------------------------------------
int8u TokenOper::FetchExpLen(Tokenfield* &p,ERR &err)
{ err = OK_no_Err;  // 置初值为正确 = 0
  if( !p )      // 如果p为空的话
   { err = ExpNULLErr; return 0; } // endif
  int8u len = 0;
  switch(p->Token)       //    预处理
  { case  '+'   : p->Token = SinglePlus; break;
    case  '-'   : p->Token = SingleNeg;  break;
  } // end switch
  switch(p->Token)
  { case ValueToken :
    case WordSToken :
    case RegisterKn :
    case   '$'      : p = p->next; len++; break;  // 执行后p指向下一个Token

    case   '('      : { p = p->next;
                        len = FetchExpLen(p,err); // 递归执行后p指向表达式的后一个Token
                        if( !len ) { err = MissEleErr; return 0; } // endif
                        if( !p || p->Token != ')' )
                         { err = MissRtErr; return 0; } // endif
                        p = p->next;
                        len += 2; break;
                      } // end case
    case NOT        :
    case HIGH       :
    case LOW        :
    case SinglePlus :
    case SingleNeg  : { p = p->next;
                        len = FetchExpLen(p,err);
                        if( !len ){ err = MissEleErr; return 0; } // endif
                        len++; break;
                      } // end case
    case  ')'       : err = MissLtErr; return 0;
    case  ','       : err = ExcesComErr; return 0;
    default         : err = ExpSyrErr; return 0;
  } // end switch
                     // Now, IsExpHead.
  if( p )            // 双目运算符
   { switch(p->Token)
     { case  '+'  :              case  '-'  :
       case  '*'  :              case  '/'  :          case  '%'  :
       case  '.'  :
       case  SHL  :              case  SHR  :
       case  AND  :              case   OR  :          case  XOR  :
       case  '='  :              case  '<'  :          case  '>'  :
       case GRtEQUKen :
       case LessEQUKn :
       case NotEqual  : { p = p->next;
                          int8u lena = FetchExpLen(p,err);
                          if(!lena) { err = MissEleErr; return 0; } // endif
                          len += lena +1; break;
                        } // end case
       // no default
     } // end switch
   } // endif
  return len;
} // end FetchExpLen
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// 判断 pt->next 指向的节点是否为操作数。是则返回操作数长度(0~2), 否则返回-1.
// 注意: 是 pt->next !! pt不能为空.
// 把pt->next所指的Token为起点的带@,#,/,等的表达式封装为操作数包,成为OPADtoken.
// 其 ExpPt 域指向表达式。
// 在使用完OPADtoken后,要释放节点!
// err = ExpNULLErr, MissRtErr, MissLtErr, ExpSyrErr, MissEleErr
//---------------------------------------------------------------------------
int8 TokenOper::FetchOpadLen(Tokenfield* pt, ERR &err)
{ err = OK_no_Err;  // 置初值为正确 = 0
  Tokenfield* t = pt->next;   // look ahead
  if(!t)       // if( t==NULL )
   { err = ExpNULLErr; return 0; } // 没有操作数, 也就是说操作数长度为0.
  int8 len = 0;
  switch( t->Token )
  { case '@' :
    case '#' :
    case '/' : len++;  pt = t;    // No breaking is right!
  } // end switch
  err = ExpToPack(pt);            // 判断 pt->next 是否数值表达式.
  if(err) { return -1; }          // 表达式有错误!
  else    { return ++len; }       // 是一个表达式.
} // end FetchOpadLen
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 获取数值表达式个数. 注意,是"p->next"!! 所以p 不能为空. 表达式个数不能>127.
// 返回 "p->next" 的数值表达式个数, 各个表达式以','作为分隔.
// 这里的表达式只包括数值表达式, 不包括字符, 字符串.
// 数值表达式本身有错count返回-1. err返回出错码.
// err = ExpNULLErr, MissRtErr, MissLtErr, ExpSyrErr, MissEleErr
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 如果是表达式之间有语法错误, err返回出错码.
// err = ExcesComErr, ExpExcessErr
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int8 TokenOper::CalExpNum(Tokenfield* pt, ERR &err)
{ if(!pt->next) { err = OK_no_Err; return 0; } // 如果它为空, 表达式个数为零.
  // Now, pt->next 不为空.
  err = ExpToPack(pt);      // pt不受影响, 看看是不是一个数值表达式.
  if( err ) { return -1; }  // 不是数值表达式, 或者数值表达式有错误! 带err返回.
  // 是数值表达式开头, p->next = "Exp Token"
  pt = pt->next->next;      // Now, p = "Exp Token"->next, maybe ','
  int8u count = 1;          // 数值表达式个数增1

  while(pt && pt->Token == ',')
  { if( !pt->next )         // 如果','后面为空
     { err = ExcesComErr; return count; } // 错误: 多余的逗号.
    // Now, ','后面还有东西.
    err = ExpToPack(pt);    // pt不受影响, 看看是不是一个数值表达式.
    if( err ) { return -1; } // 不是数值表达式, 或者数值表达式有错误! 带err返回.
  // 又是数值表达式, p->next = "Exp Token"
    pt = pt->next->next;    // Now, p = "Exp Token"->next
    count++;
  } // end while
  // 如果正确的话,pt==NULL. pt!=NULL, 说明发生了错误。
  if(pt) { err = ExpExcessErr; return count; } // 表达式后面出现多余的不合法的字符
  // Now, pt == NULL, succeed.
              //DebugMsg(cout<<"\nCalExpNum count="<<(int)count;) Debugkey;
  return count;
} // end CalExpNum
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// 注意,是"p->next"!! 所以p 不能为空. 表达式个数不能>127.
// 返回 "p->next" 的表达式个数, 各个表达式以','作为分隔.
// 这里的表达式包括数值表达式, 字符, 字符串.
// 表达式个数最大是127。
// 数值表达式本身有错count返回-1. err返回出错码.
// err = ExpNULLErr, MissRtErr, MissLtErr, ExpSyrErr, MissEleErr
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 如果是表达式之间有语法错误, err返回出错码.
// err = ExcesComErr, ExpExcessErr
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int8 TokenOper::IsCExpList(Tokenfield* pt, ERR &err)
{ err = OK_no_Err;
  int8u count = 0;
  if(!pt->next) { return 0; } // 如果它为空, 表达式个数为零.
  // Now, pt->next 不为空.
  switch(pt->next->Token)
  { case LongCharn :

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -