|
|
首先是解析为2元式,核心算法和数据结构如下:
忘记支持下划线了,加上了~~只需要修改IsEng()内联函数
**需要完整代码编译的PM我**
( 解析速度的确很快(1瞬间!),但是仍然花了几十秒,但这是CStr类的问题..最近修正了 )
// if和goto语句请您用在IDE里面用TAB对齐了察看!
namespace obj
{
typedef struct _OBJ
{
UInt32 pos;
CStr text;
_OBJ(){pos=0;text=CStr();}
}OBJ;
typedef struct _TOKEN
{
CStr type, val;
_TOKEN(){type=CStr();val=CStr();}
_TOKEN(const CStr &t,const CStr &v){ type=t; val=v; }
}TOKEN;
__forceinline IsSpace(const WChar c){ return c==L' ' || c=='\t'; }
__forceinline IsEng(const WChar c){ return (c>=L'A'&&c<=L'Z') || (c>=L'a'&&c<=L'z') || c==L'_' || c>0xFF; }
__forceinline IsCrlf(const WChar c){ return c==10 || c==13; }
__forceinline IsNum(const WChar c){ return c>=L'0' && c<=L'9'; }
const WChar _R = L'r'; // return
const WChar _I = L'i'; // identifier or keyword
const WChar _N = L'n'; // number
const WChar _F = L'f'; // float
const WChar _D = L'/'; // symbol '/'
const WChar _E = L'\0';// end of file (use '\0')
const WChar _X = L'x'; // X - means 'error'
#define stop {__asm int 3};
TOKEN *NextToken(OBJ *obj)
{
UInt32 len = obj->text.GetLen();
const WChar *buf = obj->text.ReadW();
UInt32 &p = obj->pos;
WChar c=0;
CStr ret;
CStr t;
ST_S:
c=buf[p++];
if(c==0) {ret+=c;goto ST_END;}
if(c==L'#') { goto ST_SHARP;}
if(IsSpace(c)) { goto ST_S;}
if(IsCrlf(c)) {ret+=c;goto ST_CRLF;}
if(IsEng(c)) {ret+=c;goto ST_A;}
if(IsNum(c)) {ret+=c;goto ST_0;}
if(c==L'-') {ret+=c;goto ST_MINUS;}
if(c==L'/') {ret+=c;goto ST_DIV;}
if(c==L'\\') { goto ST_BS;}
else {ret=L"error at ST_S";goto ST_ERR;}
ST_DIV:
t=_D;
return new TOKEN(t,ret);
ST_SHARP:
c=buf[p++];
if(c==0) {ret+=c;goto ST_END;}
if(IsCrlf(c)) { goto ST_S;}
else {ret=L"error at ST_SHARP";goto ST_SHARP;}
ST_CRLF:
t=_R;
return new TOKEN(t,ret);
ST_BS:
c=buf[p++];
if(c==0) {ret+=c;goto ST_END;}
if(IsSpace(c)) { goto ST_BS;}
if(IsCrlf(c)) { goto ST_BS;}
if(IsEng(c)) {ret+=c;goto ST_A;}
if(IsNum(c)) {ret+=c;goto ST_0;}
if(c==L'-') {ret+=c;goto ST_MINUS;}
if(c==L'/') {ret+=c;goto ST_DIV;}
if(c==L'\\') { goto ST_BS;}
else {ret=L"error at ST_BS";goto ST_ERR;}
ST_A:
c=buf[p++];
t=_I;
if(c==0) { goto ST_W_END;}
if(IsEng(c)) {ret+=c;goto ST_A;}
if(IsNum(c)) {ret+=c;goto ST_A;}
if(IsSpace(c)) { goto ST_W_SPACE;}
if(IsCrlf(c)) { goto ST_W_CRLF;}
if(c==L'\\') { goto ST_W_BS;}
if(c==L'/') { goto ST_W_DIV;}
else {ret=L"error at ST_A";goto ST_ERR;}
ST_W_BS:
p--;
return new TOKEN(t,ret);
ST_W_CRLF:
p--;
return new TOKEN(t,ret);
ST_W_SPACE:
return new TOKEN(t,ret);
ST_W_DIV:
p--;
return new TOKEN(t,ret);
ST_0:
c=buf[p++];
t=_N;
if(c==0) { goto ST_W_END;}
if(IsNum(c)) {ret+=c;goto ST_0;}
if(c==L'.') {ret+=c;goto ST_P;}
if(c==L'/') { goto ST_0_DIV;}
if(IsSpace(c)) { goto ST_W_SPACE;}
if(IsCrlf(c)) { goto ST_W_CRLF;}
if(c==L'\\') { goto ST_W_BS;}
if(c==L'/') { goto ST_W_DIV;}
else {ret=L"error at ST_0";goto ST_ERR;}
ST_0_DIV:
p--;
return new TOKEN(t,ret);
ST_MINUS:
c=buf[p++];
if(c==0) {ret=L"error at ST_MINUS";goto ST_ERR;}
if(IsNum(c)) {ret+=c;goto ST_0;}
else {ret=L"error at ST_MINUS";goto ST_ERR;}
ST_P:
c=buf[p++];
if(c==0) {ret=L"error at ST_P";goto ST_ERR;}
if(IsNum(c)) {ret+=c;goto ST_P2;}
else {ret=L"";goto ST_ERR;}
ST_P2:
c=buf[p++];
t=_F;
if(c==0) { goto ST_W_END;}
if(IsNum(c)) {ret+=c;goto ST_P2;}
if(c=='/') { goto ST_0_DIV;}
if(IsSpace(c)) { goto ST_W_SPACE;}
if(IsCrlf(c)) { goto ST_W_CRLF;}
if(c==L'\\') { goto ST_W_BS;}
if(c==L'/') { goto ST_W_DIV;}
else {ret=L"error at ST_P2";goto ST_ERR;}
ST_END:
t=_E;
return new TOKEN(t,ret);
ST_W_END:
p--;
return new TOKEN(t,ret);
ST_ERR:
p--;
t=_X;
return new TOKEN(t,ret);
}
////////////////////////////////////////////////////////////////////////////////
// 由于解析阶段已经检查过语法,所以可以确保CStr型的ARG信息总是正确的
typedef struct _ARG
{
UByte * count;
CStr * parts;
}ARG;
typedef struct _LINE
{
CStr type;
UInt16 count;
ARG * args;
}LINE;
} // end of n.s. obj
////////////////////////////////////////////////////////////////////////////////
using namespace obj;
void COBJDlg::OnbtPhaseWord()
{
OBJ obj;
obj.pos=0;
CString tmp;
GetDlgItemText(txObj,tmp);
obj.text=CStr(tmp.GetBuffer(0),936);
SList<TOKEN *> list;
CStr op;
while(true)
{
TOKEN *ret=NextToken(&obj);
if(CStr(_X)==ret->type)goto Error;
list.Add(ret);
if(CStr(_E)==ret->type)
{
op+=L"(0,0)";
break;
}
else if(CStr(_R)==ret->type)
{
op+=L"(r,r)";
}
else
{
op+=L"("; op+=ret->type; op+=L","; op+=ret->val; op+=L")";
}
}
CDialog::SetDlgItemText(txWord,TmpCharArrayA(op));
return;
Error:
CDialog::SetDlgItemText(txWord,TmpCharArrayA(list.Get(list.Count()-1)->val));
}
|
-
|