📄 tokenoper_c.cpp
字号:
//---------------------------------------------------------------------------
// 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 + -