📄 interpreter.cpp
字号:
#include "stdafx.h"
#include "ScriptEngine.h"
#include <comdef.h>
void CScriptEngine::__level6(VARIANT* pVar)
{
switch( t ) {
case OP_PAREN_L:
{
t = tok.GetToken();
_variant_t var;
__level1(&var);
if( t != OP_PAREN_R ) throw EXCEP_PAREN;
*pVar = var.Detach();
}
break;
case OP_STRING:
{
_variant_t var = t.pstr;
*pVar = var.Detach();
}
break;
case OP_INTEGER:
{
_variant_t var = t.value;
var.ChangeType(VT_I4);
*pVar = var.Detach();
}
break;
case OP_NUMBER:
{
_variant_t var = t.value;
_com_util::CheckError(::VariantChangeTypeEx(&var, &var, 1033, 0, VT_R8));
*pVar = var.Detach();
}
break;
case OP_INDENTIFIER:
{
__var_retrieve(pVar);
switch( t ) {
case OP_DOT:
{
t = tok.GetToken();
if( t != OP_INDENTIFIER ) throw EXCEP_NAMEEXPECTED;
if( t == L"toString" ) _com_util::CheckError(::VariantChangeType(pVar, pVar, 0, VT_BSTR));
else if( t == L"toDate" ) _com_util::CheckError(::VariantChangeType(pVar, pVar, 0, VT_DATE));
else if( t == L"toInteger" ) _com_util::CheckError(::VariantChangeType(pVar, pVar, 0, VT_I4));
else if( t == L"toNumber" ) _com_util::CheckError(::VariantChangeTypeEx(pVar, pVar, 1033, 0, VT_R8));
else throw EXCEP_NOTFOUND;
if( tok.GetToken() != OP_PAREN_L ) throw EXCEP_PAREN;
if( tok.GetToken() != OP_PAREN_R ) throw EXCEP_PAREN;
}
break;
case OP_INC:
case OP_DEC:
{
_variant_t one(1L);
if( t == OP_INC ) _com_util::CheckError(::VarAdd(pVar, &one, pVar));
else _com_util::CheckError(::VarSub(pVar, &one, pVar));
}
break;
default:
return;
}
}
break;
}
t = tok.GetToken();
}
void CScriptEngine::__level5(VARIANT* pVar)
{
bool bUnary = false;
if( t == OP_PLUS || t == OP_MINUS ) {
bUnary = true;
t = tok.GetToken();
}
__level6(pVar);
if( bUnary ) _com_util::CheckError(::VarNeg(pVar, pVar));
}
void CScriptEngine::__level4(VARIANT* pVar)
{
__level5(pVar);
while( t == OP_NOT ) {
_com_util::CheckError(::VarNot(pVar, pVar));
t = tok.GetToken();
}
}
void CScriptEngine::__level3(VARIANT* pVar)
{
__level4(pVar);
while( t == OP_MUL || t == OP_DIV ) {
TOKEN tOp = t;
t = tok.GetToken();
_variant_t var;
__level4(&var);
switch( tOp ) {
case OP_MUL:
_com_util::CheckError(::VarMul(pVar, &var, pVar));
break;
case OP_DIV:
_com_util::CheckError(::VarDiv(pVar, &var, pVar));
break;
}
}
}
void CScriptEngine::__level2(VARIANT* pVar)
{
__level3(pVar);
while( t == OP_PLUS || t == OP_MINUS ) {
TOKEN tOp = t;
t = tok.GetToken();
_variant_t var;
__level3(&var);
switch( tOp ) {
case OP_PLUS:
var.ChangeType(pVar->vt);
_com_util::CheckError(::VarAdd(pVar, &var, pVar));
break;
case OP_MINUS:
var.ChangeType(pVar->vt);
_com_util::CheckError(::VarSub(pVar, &var, pVar));
break;
}
}
}
void CScriptEngine::__level1(VARIANT* pVar)
{
__level2(pVar);
while( t == OP_OPERATOR ) {
TOKEN tOp = t;
t = tok.GetToken();
_variant_t var;
__level2(&var);
HRESULT Hr = ::VarCmp(pVar, &var, LOCALE_USER_DEFAULT, 0);
if( tOp == L"==" ) var = Hr == VARCMP_EQ;
else if( tOp == L"!=" ) var = Hr != VARCMP_EQ;
else if( tOp == L"<" ) var = Hr == VARCMP_LT;
else if( tOp == L">" ) var = Hr == VARCMP_GT;
else if( tOp == L"<=" ) var = Hr == VARCMP_LT || Hr == VARCMP_EQ;
else if( tOp == L">=" ) var = Hr == VARCMP_GT || Hr == VARCMP_EQ;
::VariantCopy(pVar, &var);
}
}
void CScriptEngine::__level0(VARIANT* pVar)
{
__level1(pVar);
while( t == OP_AND || t == OP_OR || t == OP_XOR ) {
TOKEN tOp = t;
t = tok.GetToken();
_variant_t var;
__level1(&var);
switch( tOp ) {
case OP_AND:
_com_util::CheckError(::VarAnd(pVar, &var, pVar));
break;
case OP_OR:
_com_util::CheckError(::VarOr(pVar, &var, pVar));
break;
case OP_XOR:
_com_util::CheckError(::VarXor(pVar, &var, pVar));
break;
}
}
}
void CScriptEngine::__eval(VARIANT* pVar)
{
__level0(pVar);
while( t == OP_COMMA ) {
t = tok.GetToken();
__level0(pVar);
}
}
int CScriptEngine::__pushstack()
{
STACKLEVEL& stack = m_Stack[m_nStackLevel];
stack.iVarIndex = m_nVars;
stack.pstrCode = tok.m_pstr;
stack.iLineNo = tok.m_iLineNo;
stack.t = t.type;
::VariantInit(&stack.vRet);
if( ++m_nStackLevel >= MAX_STACKDEPTH ) throw EXCEP_STACKOVERFLOW;
return m_nStackLevel;
}
void CScriptEngine::__popstack(int iStack)
{
STACKLEVEL& stack = m_Stack[iStack - 1];
int i;
for( i = m_nVars - 1; i >= stack.iVarIndex; --i ) ::VariantClear(&m_vars[i].vValue);
for( i = m_nStackLevel - 1; i >= iStack - 1; --i ) ::VariantClear(&m_Stack[i].vRet);
tok.Assign(stack.pstrCode, stack.iLineNo);
m_nVars = stack.iVarIndex;
t = TOKEN(stack.t);
m_nStackLevel = iStack - 1;
}
void CScriptEngine::__block()
{
if( t == OP_SEMICOLON ) return;
if( t != OP_BRACE_L ) {
__statement();
t = tok.GetToken();
}
else {
int iStack = __pushstack();
__exec(OP_BRACE_R);
__popstack(iStack);
tok.SkipTo(t, OP_BRACE_R);
}
if( t == OP_SEMICOLON ) t = tok.GetToken();
}
void CScriptEngine::__var_assign()
{
TOKEN tName = t;
_variant_t res;
TOKEN tOp = tok.PeekToken();
switch( tOp ) {
case OP_PAREN_L:
{
_variant_t v;
__var_retrieve(&v);
}
return;
case OP_EQUAL:
case OP_PLUSEQUAL:
case OP_MINUSEQUAL:
tok.GetToken();
t = tok.GetToken();
__eval(&res);
break;
case OP_INC:
case OP_DEC:
__eval(&res);
break;
case OP_DOT:
break;
default:
throw EXCEP_SYNTAXERROR;
}
for( int i = m_nVars - 1; i >= 0; --i ) {
if( tName == m_vars[i].szName ) {
switch( tOp ) {
case OP_INC:
case OP_DEC:
case OP_EQUAL: _com_util::CheckError(::VariantCopy(&m_vars[i].vValue, &res)); break;
case OP_PLUSEQUAL: _com_util::CheckError(::VarAdd(&m_vars[i].vValue, &res, &m_vars[i].vValue)); break;
case OP_MINUSEQUAL: _com_util::CheckError(::VarSub(&m_vars[i].vValue, &res, &m_vars[i].vValue)); break;
default: throw EXCEP_SYNTAXERROR;
}
return;
}
}
for( i = 0; i < m_nObjects; i++ ) {
if( wcslen(m_Objects[i].szName) == 0 ) {
if( m_Objects[i].pCallback->SetProperty(tName, res) ) return;
}
}
for( i = 0; i < m_nObjects; i++ ) {
if( tName == m_Objects[i].szName ) {
if( tok.GetToken() != OP_DOT ) throw EXCEP_NAMEEXPECTED;
t = tok.GetToken();
tName = t;
if( tok.PeekToken() == OP_EQUAL ) {
tok.GetToken();
t = tok.GetToken();
__eval(&res);
}
if( !m_Objects[i].pCallback->SetProperty(tName, res) ) throw EXCEP_NOTFOUND;
return;
}
}
throw EXCEP_NOTFOUND;
}
void CScriptEngine::__var_retrieve(VARIANT* pVar)
{
int i;
for( i = m_nVars - 1; i >= 0; --i ) {
if( t == m_vars[i].szName ) {
::VariantCopy(pVar, &m_vars[i].vValue);
t = tok.GetToken();
return;
}
}
for( i = 0; i < m_nObjects; i++ ) {
if( t == m_Objects[i].szName ) {
if( pVar->vt == VT_UNKNOWN ) pVar->vt = VT_ERROR;
if( tok.GetToken() != OP_DOT ) throw EXCEP_NAMEEXPECTED;
TOKEN tName = tok.GetToken();
t = tok.GetToken();
if( t == OP_PAREN_L ) {
t = tok.GetToken();
int nArgs = MAX_ARGUMENTS;
_variant_t args[MAX_ARGUMENTS];
__var_getargs(args, nArgs);
if( !m_Objects[i].pCallback->Method(tName, args, nArgs, pVar) ) throw EXCEP_NOTFOUND;
}
else {
if( !m_Objects[i].pCallback->GetProperty(tName, pVar) ) throw EXCEP_NOTFOUND;
}
if( pVar->vt == VT_ERROR ) throw EXCEP_ERROR;
return;
}
}
TOKEN tName = t;
t = tok.GetToken();
if( t == OP_PAREN_L )
{
t = tok.GetToken();
int nArgs = MAX_ARGUMENTS;
_variant_t args[MAX_ARGUMENTS];
__var_getargs(args, nArgs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -