static int parse(ej_t *ep, int state, int flags) { a_assert(ep); switch (state) { /* * Any statement, function arguments or conditional expressions */ case STATE_STMT: if ((state = parseStmt(ep, state, flags)) != STATE_STMT_DONE && state != STATE_EOF && state != STATE_STMT_BLOCK_DONE && state != STATE_RET) { state = STATE_ERR; } break; case STATE_DEC: if ((state = parseStmt(ep, state, flags)) != STATE_DEC_DONE && state != STATE_EOF) { state = STATE_ERR; } break; case STATE_EXPR: if ((state = parseStmt(ep, state, flags)) != STATE_EXPR_DONE && state != STATE_EOF) { state = STATE_ERR; } break; /* * Variable declaration list */ case STATE_DEC_LIST: state = parseDeclaration(ep, state, flags); break; /* * Function argument string */ case STATE_ARG_LIST: state = parseArgs(ep, state, flags); break; /* * Logical condition list (relational operations separated by &&, ||) */ case STATE_COND: state = parseCond(ep, state, flags); break; /* * Expression list */ case STATE_RELEXP: state = parseExpr(ep, state, flags); break; } if (state == STATE_ERR && ep->error == NULL) { ejError(ep, T("Syntax error")); } return state; }
/** * Atom = ( "(" [ Expr [{ "," Expr }] ] ")" ) * | ( "[" [{ Expr }] "]" ) * | FnLit | Path | <Str> | <Symbol> */ static ast* parseAtom (parserCtx* ctx) { ast* node; if (try_match(ctx, "(")) { /*Empty brackets => unit literal*/ if (see(ctx, ")")) node = astCreateUnitLit(); else { node = parseExpr(ctx); /*Tuple literal*/ if (see(ctx, ",")) { vector(ast*) nodes = vectorInit(3, malloc); vectorPush(&nodes, node); while (try_match(ctx, ",")) vectorPush(&nodes, parseExpr(ctx)); node = astCreateTupleLit(nodes); } } match(ctx, ")"); /*List literal*/ } else if (try_match(ctx, "[")) { vector(ast*) nodes = vectorInit(4, malloc); if (waiting_for(ctx, "]")) do { vectorPush(&nodes, parseExpr(ctx)); } while (try_match(ctx, ",")); node = astCreateListLit(nodes); match(ctx, "]"); } else if (see(ctx, "\\")) { node = parseFnLit(ctx); } else if (see(ctx, "true") || see(ctx, "false")) { node = astCreateBoolLit(see(ctx, "true")); accept(ctx); } else if (see_kind(ctx, tokenIntLit)) { node = astCreateIntLit(atoi(ctx->current.buffer)); accept(ctx); } else if (see_kind(ctx, tokenStrLit)) { node = astCreateStrLit(ctx->current.buffer); accept(ctx); } else if (see_kind(ctx, tokenNormal)) { sym* symbol; if (isPathToken(ctx->current.buffer)) node = parsePath(ctx); else if ((symbol = symLookup(ctx->scope, ctx->current.buffer))) node = astCreateSymbol(symbol); else node = astCreateFileLit(ctx->current.buffer); accept(ctx); } else { expected(ctx, "expression"); node = astCreateInvalid(); } return node; }
static bool parseSpec(ParseTreeNode* parentNode) { // Store current state for rolling back if we fail int curToken = said_token; int curTreePos = said_tree_pos; ParseTreeNode* curRightChild = parentNode->right; ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0); bool ret = false; bool found; ParseTreeNode* newParent = parentNode; found = parseExpr(newNode); if (found) { // Sentence part 1 found said_attach_subtree(newParent, 0x141, 0x149, newNode); newParent = newParent->right; ret = true; } bool nonempty; found = parsePart2(newParent, nonempty); if (found) { ret = true; if (nonempty) // non-empty part found newParent = newParent->right; found = parsePart3(newParent, nonempty); if (found) { if (nonempty) newParent = newParent->right; } } if (said_tokens[said_token] == TOKEN_GT) { said_token++; newNode = said_branch_node(said_next_node(), 0, said_leaf_node(said_next_node(), TOKEN_GT)); said_attach_subtree(newParent, 0x14B, TOKEN_GT, newNode); } if (ret) return true; // Rollback said_token = curToken; said_tree_pos = curTreePos; parentNode->right = curRightChild; return false; }
// Load a value according to the operation void Expression::loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame) { int16 dimCount; uint16 temp; int16 temp2; int16 offset; int16 dim; byte *arrDescPtr; int32 prevPrevVal; int32 prevVal; int32 curVal; switch (operation) { case OP_ARRAY_INT8: case OP_ARRAY_INT32: case OP_ARRAY_INT16: case OP_ARRAY_STR: *stackFrame.opers = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16; temp = _vm->_game->_script->readInt16(); dimCount = _vm->_game->_script->readByte(); arrDescPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos(); _vm->_game->_script->skip(dimCount); offset = 0; for (dim = 0; dim < dimCount; dim++) { temp2 = parseValExpr(OP_END_MARKER); offset = offset * arrDescPtr[dim] + temp2; } if (operation == OP_ARRAY_INT8) *stackFrame.values = (int8) READ_VARO_UINT8(varBase + temp + offset); else if (operation == OP_ARRAY_INT32) *stackFrame.values = READ_VARO_UINT32(varBase + temp * 4 + offset * 4); else if (operation == OP_ARRAY_INT16) *stackFrame.values = (int16) READ_VARO_UINT16(varBase + temp * 2 + offset * 2); else if (operation == OP_ARRAY_STR) { *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8( varBase + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4), kInterVar); if (_vm->_game->_script->peekByte() == 13) { _vm->_game->_script->skip(1); temp2 = parseValExpr(OP_END_MARKER); *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = READ_VARO_UINT8(varBase + temp * 4 + offset * 4 * _vm->_global->_inter_animDataSize + temp2); } } break; case OP_LOAD_VAR_INT16: *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readUint16() * 2); break; case OP_LOAD_VAR_INT8: *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = (int8) READ_VARO_UINT8(varBase + _vm->_game->_script->readUint16()); break; case OP_LOAD_IMM_INT32: *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = _vm->_game->_script->readInt32(); break; case OP_LOAD_IMM_INT16: *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = _vm->_game->_script->readInt16(); break; case OP_LOAD_IMM_INT8: *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = _vm->_game->_script->readInt8(); break; case OP_LOAD_IMM_STR: *stackFrame.opers = OP_LOAD_IMM_STR; *stackFrame.values = encodePtr((byte *)_vm->_game->_script->readString(), kExecPtr); break; case OP_LOAD_VAR_INT32: *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = READ_VARO_UINT32(varBase + _vm->_game->_script->readUint16() * 4); break; case OP_LOAD_VAR_INT32_AS_INT16: *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readUint16() * 4); break; case OP_LOAD_VAR_STR: *stackFrame.opers = OP_LOAD_IMM_STR; temp = _vm->_game->_script->readUint16() * 4; *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(varBase + temp), kInterVar); if (_vm->_game->_script->peekByte() == 13) { _vm->_game->_script->skip(1); temp += parseValExpr(OP_END_MARKER); *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = READ_VARO_UINT8(varBase + temp); } break; case OP_FUNC: operation = _vm->_game->_script->readByte(); parseExpr(OP_END_EXPR, 0); switch (operation) { case FUNC_SQRT1: case FUNC_SQRT2: case FUNC_SQRT3: curVal = 1; prevVal = 1; do { prevPrevVal = prevVal; prevVal = curVal; curVal = (curVal + _resultInt / curVal) / 2; } while ((curVal != prevVal) && (curVal != prevPrevVal)); _resultInt = curVal; break; case FUNC_SQR: _resultInt = _resultInt * _resultInt; break; case FUNC_ABS: if (_resultInt < 0) _resultInt = -_resultInt; break; case FUNC_RAND: _resultInt = _vm->_util->getRandom(_resultInt); break; } *stackFrame.opers = OP_LOAD_IMM_INT16; *stackFrame.values = _resultInt; break; } }
int16 Expression::parseValExpr(byte stopToken) { parseExpr(stopToken, 0); return _resultInt; }
//- AN ---------------------------------------------- // Компиляция строки BufPtr в байткод CurMacroBuffer //- AN ---------------------------------------------- int __parseMacroString(DWORD *&CurMacroBuffer, int &CurMacroBufferSize, const wchar_t *BufPtr) { _KEYMACRO(CleverSysLog Clev(L"parseMacroString")); //_KEYMACRO(SysLog(L"BufPtr[%p]='%s'", BufPtr,BufPtr)); _macro_nErr = 0; _macro_nLine= 0; _macro_nPos = 0; pSrcString = emptyString; inloop = 0; /*pSrcString = */oSrcString = sSrcString = emptyString; if (!BufPtr || !*BufPtr) { keyMacroParseError(err_ZeroLengthMacro); return FALSE; } bool useUDL=true; const wchar_t *NewBufPtr; UserDefinedList MacroSrcList(ULF_NOTRIM|ULF_NOUNQUOTE, L"\r\n"); if(!MacroSrcList.Set(BufPtr)) useUDL=false; // все в одну строку //{ // _SVS(SysLog(L"MacroSrcList.GetTotal()=%d",MacroSrcList.GetTotal())); // while((NewBufPtr=MacroSrcList.GetNext()) ) // _SVS(SysLog(L"[%s]",NewBufPtr)); // MacroSrcList.Reset(); //} size_t SizeCurKeyText = (StrLength(BufPtr)*2)*sizeof(wchar_t); string strCurrKeyText; //- AN ---------------------------------------------- // Буфер под парсинг выражений //- AN ---------------------------------------------- DWORD *dwExprBuff = (DWORD*)xf_malloc(SizeCurKeyText*sizeof(DWORD)); if (!dwExprBuff) return FALSE; TExec exec; wchar_t varName[256]; DWORD KeyCode, *CurMacro_Buffer = nullptr; if(useUDL) BufPtr=MacroSrcList.GetNext(); pSrcString=BufPtr; for (;;) { int Size = 1; int SizeVarName = 0; const wchar_t *oldBufPtr = BufPtr; if (!(BufPtr = __GetNextWord(BufPtr, strCurrKeyText, _macro_nLine))) { if(!useUDL) break; NewBufPtr=MacroSrcList.GetNext(); if(!NewBufPtr) break; _macro_nLine++; pSrcString=BufPtr=NewBufPtr; continue; } _SVS(SysLog(L"_macro_nLine = [%d]",_macro_nLine)); _SVS(SysLog(L"BufPtr = [%s]",BufPtr)); _SVS(SysLog(L"pSrcString = [%s]",pSrcString)); _SVS(SysLog(L"strCurrKeyText = [%s]",strCurrKeyText.CPtr())); //- AN ---------------------------------------------- // Проверка на строковый литерал // Сделаем $Text опциональным //- AN ---------------------------------------------- if (strCurrKeyText.At(0) == L'\"' && strCurrKeyText.At(1)) { KeyCode = MCODE_OP_PLAINTEXT; BufPtr = oldBufPtr; } else if ((KeyCode = KeyNameMacroToKey(strCurrKeyText)) == (DWORD)-1 && (KeyCode = KeyNameToKey(strCurrKeyText)) == (DWORD)-1) { int ProcError=0; if (strCurrKeyText.At(0) == L'%' && ( (IsAlphaNum(strCurrKeyText.At(1)) || strCurrKeyText.At(1) == L'_') || ( strCurrKeyText.At(1) == L'%' && (IsAlphaNum(strCurrKeyText.At(2)) || strCurrKeyText.At(2)==L'_') ) ) ) { BufPtr = oldBufPtr; while (*BufPtr && (IsSpace(*BufPtr) || IsEol(*BufPtr))) { if (IsEol(*BufPtr)) { _macro_nLine++;//TODO!!! } BufPtr++; } ClearArray(varName); KeyCode = MCODE_OP_SAVE; wchar_t* p = varName; const wchar_t* s = strCurrKeyText.CPtr()+1; if (*s == L'%') *p++ = *s++; wchar_t ch; *p++ = *s++; while ((iswalnum(ch = *s++) || (ch == L'_'))) *p++ = ch; *p = 0; size_t Length = (StrLength(varName)+1)*sizeof(wchar_t); // строка должна быть выровнена на 4 SizeVarName = static_cast<int>(Length/sizeof(DWORD)); if (Length == sizeof(wchar_t) || (Length % sizeof(DWORD)) ) // дополнение до sizeof(DWORD) нулями. SizeVarName++; _SVS(SysLog(L"BufPtr=%s",BufPtr)); BufPtr += Length/sizeof(wchar_t); _SVS(SysLog(L"BufPtr=%s",BufPtr)); Size += parseExpr(BufPtr, dwExprBuff, L'=', L';'); if (_macro_nErr) { ProcError++; } } else { // проверим вариант, когда вызвали функцию, но результат не присвоили, // например, вызвали MsgBox(), но результат неважен // тогда SizeVarName=1 и varName="" wchar_t *lpwszCurrKeyText = strCurrKeyText.GetBuffer(); wchar_t *Brack=(wchar_t *)wcspbrk(lpwszCurrKeyText,L"( "), Chr=0; if (Brack) { Chr=*Brack; *Brack=0; } if (funcLook(lpwszCurrKeyText) != MCODE_F_NOFUNC) { if (Brack) *Brack=Chr; BufPtr = oldBufPtr; while (*BufPtr && (IsSpace(*BufPtr) || IsEol(*BufPtr))) { if (IsEol(*BufPtr)) { _macro_nLine++;//TODO!!! } BufPtr++; } Size += parseExpr(BufPtr, dwExprBuff, 0, 0); /* // этого пока ненадо, считаем, что ';' идет сразу за функцией, иначе это отдельный символ ';', который нужно поместить в поток while ( *BufPtr && (IsSpace(*BufPtr) || IsEol(*BufPtr)) ) { if (IsEol(*BufPtr)) { _macro_nLine++;//TODO!!! } BufPtr++; } */ if (*BufPtr == L';') BufPtr++; // здесь Size не увеличиваем, т.к. мы прокидываем символ ';' //Size--; //??? if (_macro_nErr) { ProcError++; } else { KeyCode=MCODE_OP_SAVE; SizeVarName=1; ClearArray(varName); } } else { if (Brack) *Brack=Chr; ProcError++; } strCurrKeyText.ReleaseBuffer(); } if (ProcError) { if (!_macro_nErr) //keyMacroParseError(err_Unrecognized_keyword, strCurrKeyText, strCurrKeyText,strCurrKeyText); keyMacroParseError(err_Unrecognized_keyword, oldBufPtr, pSrcString, strCurrKeyText); if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } } else if (!(strCurrKeyText.At(0) == L'$' && strCurrKeyText.At(1))) { Size=3; KeyCode=MCODE_OP_KEYS; } switch (KeyCode) { // $Text // ------------------------------------- // MCODE_OP_PLAINTEXT // <expr> case MCODE_OP_PLAINTEXT: { Size += parseExpr(BufPtr, dwExprBuff, 0, 0); break; } // $If (expr) ... $End // ------------------------------------- // <expr> // MCODE_OP_JZ p1=*+0 // addr1 ------------+ // ... | // MCODE_OP_JMP | // +--------- addr2 | // | ... <-----------+ // +--------> MCODE_OP_END // или // <expr> // MCODE_OP_JZ p1=*+0 // addr1 ------------+ // ... | // MCODE_OP_END <-----------+ case MCODE_OP_IF: { Size += parseExpr(BufPtr, dwExprBuff, L'(', L')'); if (!exec.add(emmThen, CurMacroBufferSize+Size)) { if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } Size++; break; } case MCODE_OP_ELSE: { Size++; break; } // $Rep (expr) ... $End // ------------------------------------- // <expr> // MCODE_OP_SAVEREPCOUNT 1 // +--------> MCODE_OP_REP p1=* // | <counter> 3 // | <counter> 4 // | MCODE_OP_JZ 5 p2=*+2 // | addr1 ------------+ // | ... | // | MCODE_OP_JMP | // +--------- addr2 | // MCODE_OP_END <-----------+ case MCODE_OP_REP: { inloop++; Size += parseExpr(BufPtr, dwExprBuff, L'(', L')'); if (!exec.add(emmRep, CurMacroBufferSize+Size, CurMacroBufferSize+Size+4)) //??? 3 { if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } Size += 5; // естественно, размер будет больше = 4 break; } // $While (expr) ... $End // ------------------------------------- // +--------> <expr> // | MCODE_OP_JZ CurMacroBufferSize + Size - 2 // | addr1 ------------+ CurMacroBufferSize + Size - 1 // | ... | ... // | MCODE_OP_JMP | CurMacroBufferSize + Size - 3 // +--------- addr2 | CurMacroBufferSize + Size - 2 // MCODE_OP_END <-----------+ CurMacroBufferSize + Size - 1 // CurMacroBufferSize + Size case MCODE_OP_WHILE: { inloop++; Size += parseExpr(BufPtr, dwExprBuff, L'(', L')'); if (!exec.add(emmWhile, CurMacroBufferSize, CurMacroBufferSize+Size)) { if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } Size++; break; } // $continue // ------------------------------------- // ^ MCODE_OP_CONTINUE // | MCODE_OP_JMP // +--------- addr case MCODE_OP_CONTINUE: { Size++; // Место под адрес break; } // $break // ------------------------------------- // MCODE_OP_BREAK // MCODE_OP_JMP // addr --> case MCODE_OP_BREAK: { Size++; // Место под адрес break; } case MCODE_OP_END: { switch (exec().state) { case emmRep: case emmWhile: Size += 2; // Место под дополнительный JMP break; default: break; } break; } } if (_macro_nErr) { if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } if (!BufPtr) // ??? break; // код найден, добавим этот код в буфер последовательности. CurMacro_Buffer = (DWORD *)xf_realloc(CurMacro_Buffer,sizeof(*CurMacro_Buffer)*(CurMacroBufferSize+Size+SizeVarName)); if (!CurMacro_Buffer) { CurMacroBuffer = nullptr; CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } switch (KeyCode) { case MCODE_OP_PLAINTEXT: { _SVS(SysLog(L"[%d] Size=%u",__LINE__,Size)); memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD)); CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode; break; } case MCODE_OP_SAVE: { memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD)); CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode; memcpy(CurMacro_Buffer+CurMacroBufferSize+Size, varName, SizeVarName*sizeof(DWORD)); break; } case MCODE_OP_IF: { memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD)); CurMacro_Buffer[CurMacroBufferSize+Size-2] = MCODE_OP_JZ; break; } case MCODE_OP_REP: { memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD)); CurMacro_Buffer[CurMacroBufferSize+Size-6] = MCODE_OP_SAVEREPCOUNT; CurMacro_Buffer[CurMacroBufferSize+Size-5] = KeyCode; CurMacro_Buffer[CurMacroBufferSize+Size-4] = 0; // Initilize 0 CurMacro_Buffer[CurMacroBufferSize+Size-3] = 0; CurMacro_Buffer[CurMacroBufferSize+Size-2] = MCODE_OP_JZ; break; } case MCODE_OP_WHILE: { memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD)); CurMacro_Buffer[CurMacroBufferSize+Size-2] = MCODE_OP_JZ; break; } case MCODE_OP_ELSE: { if (exec().state == emmThen) { exec().state = emmElse; CurMacro_Buffer[exec().pos1] = CurMacroBufferSize+2; exec().pos1 = CurMacroBufferSize; CurMacro_Buffer[CurMacroBufferSize] = 0; } else // тут $else и не предвиделось :-/ { keyMacroParseError(err_Not_expected_ELSE, BufPtr, pSrcString); // strCurrKeyText if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } break; } case MCODE_OP_BREAK: case MCODE_OP_CONTINUE: { TExecItem *ei=nullptr; if (!inloop || (KeyCode==MCODE_OP_CONTINUE && exec.findnearloop(&ei) == -1)) { keyMacroParseError(KeyCode==MCODE_OP_CONTINUE?err_Continue_Outside_The_Loop:err_Break_Outside_The_Loop, oldBufPtr, pSrcString);//BufPtr, pSrcString); // strCurrKeyText if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } CurMacro_Buffer[CurMacroBufferSize+Size-2] = KeyCode==MCODE_OP_CONTINUE?MCODE_OP_JMP:MCODE_OP_BREAK; CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode==MCODE_OP_CONTINUE?ei->pos1:0; break; } case MCODE_OP_END: { switch (exec().state) { case emmMain: // тут $end и не предвиделось :-/ keyMacroParseError(err_Not_expected_END, BufPtr, pSrcString); // strCurrKeyText if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; case emmThen: CurMacro_Buffer[exec().pos1-1] = MCODE_OP_JZ; CurMacro_Buffer[exec().pos1+0] = CurMacroBufferSize+Size-1; CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode; break; case emmElse: CurMacro_Buffer[exec().pos1-0] = MCODE_OP_JMP; CurMacro_Buffer[exec().pos1+1] = CurMacroBufferSize+Size-1; CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode; break; case emmRep: case emmWhile: inloop--; CurMacro_Buffer[exec().pos2] = CurMacroBufferSize+Size-1; CurMacro_Buffer[CurMacroBufferSize+Size-3] = MCODE_OP_JMP; CurMacro_Buffer[CurMacroBufferSize+Size-2] = exec().pos1; CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode; CorrectBreakCode(CurMacro_Buffer,CurMacro_Buffer+exec().pos1,CurMacro_Buffer+(CurMacroBufferSize+Size-1)); break; } if (!exec.del()) // Вообще-то этого быть не должно, но подстрахуемся { if (CurMacro_Buffer ) { xf_free(CurMacro_Buffer); CurMacroBuffer = nullptr; } CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } break; } case MCODE_OP_KEYS: { CurMacro_Buffer[CurMacroBufferSize+Size-3]=MCODE_OP_KEYS; CurMacro_Buffer[CurMacroBufferSize+Size-2]=KeyNameToKey(strCurrKeyText); CurMacro_Buffer[CurMacroBufferSize+Size-1]=MCODE_OP_ENDKEYS; break; } default: CurMacro_Buffer[CurMacroBufferSize]=KeyCode; } // end switch(KeyCode) CurMacroBufferSize += Size+SizeVarName; } // END for (;;) if (CurMacroBufferSize == 1) { CurMacro_Buffer = (DWORD *)xf_realloc(CurMacro_Buffer,sizeof(*CurMacro_Buffer)*(CurMacroBufferSize+1)); if (!CurMacro_Buffer) { CurMacroBuffer = nullptr; CurMacroBufferSize = 0; xf_free(dwExprBuff); return FALSE; } CurMacro_Buffer[CurMacroBufferSize]=MCODE_OP_NOP; CurMacroBufferSize++; } #ifdef _DEBUG #ifdef SYSLOG_KEYMACRO SysLogDump(L"Macro Buffer",0,(LPBYTE)CurMacro_Buffer,CurMacroBufferSize*sizeof(DWORD),nullptr); SysLog(L"<ByteCode>{"); if (CurMacro_Buffer) { int ii; for (ii = 0 ; ii < CurMacroBufferSize ; ii++) printKeyValue(CurMacro_Buffer, ii); } else SysLog(L"??? is nullptr"); SysLog(L"}</ByteCode>"); #endif #endif if (CurMacroBufferSize > 1) CurMacroBuffer = CurMacro_Buffer; else if (CurMacro_Buffer) { CurMacroBuffer = reinterpret_cast<DWORD*>((intptr_t)(*CurMacro_Buffer)); xf_free(CurMacro_Buffer); } xf_free(dwExprBuff); if (exec().state != emmMain) { keyMacroParseError(err_Unexpected_EOS, strCurrKeyText, strCurrKeyText); return FALSE; } if (_macro_nErr) { return FALSE; } return TRUE; }
/** Parse a function expression fun (x,y,z) <body_expr> */ Tuple parseFunExpr(Input* input) { // Optional function name Tuple name; // Try to parse parse the optional function name try { input->eatWS(); name = parseIdentStr(input); } catch (ParseError e) { name = Tuple(""); } // If there is no parameter list input->eatWS(); if (!input->matchCh('(')) { throw ParseError( input, "expected parameter list in function expression" ); } // Allocate an array for the parameter declarations std::vector<Value> params; // Until the end of the list for (;;) { // Read whitespace input->eatWS(); // If this is the end of the list if (input->matchCh(')')) break; // Parse an identifier params.push_back(parseIdentStr(input)); // Read whitespace input->eatWS(); // If this is the end of the list if (input->matchCh(')')) break; // If this is not the first element, there must be a separator if (!input->matchCh(',')) { throw ParseError(input, "expected comma separator in parameter list"); } } // Parse the function body auto bodyExpr = parseExpr(input); return Tuple{ Tuple("fun"), name, Tuple(params), bodyExpr }; }
Expression* Expression_parse(const char** expr) { Expression* ret = NULL; Variable* var; Value* val; const char* equals = strchr(*expr, '='); if(equals == NULL) { /* No assignment, just a plain expression. */ return parseExpr(expr); } /* There is an assignment */ /* First, parse the right side of the assignment */ equals++; val = Value_parse(&equals, 0, 0); if(val->type == VAL_ERR) { /* A parse error occurred */ var = VarErr(Error_copy(val->err)); Value_free(val); return Expression_new(var); } if(val->type == VAL_END) { /* Empty input */ Value_free(val); var = VarErr(earlyEnd()); return Expression_new(var); } /* Now parse the left side */ char* name = nextToken(expr); if(name == NULL) { Value_free(val); var = VarErr(syntaxError("No variable to assign to.")); return Expression_new(var); } trimSpaces(expr); if(**expr == '(') { /* Defining a function */ (*expr)++; /* Array of argument names */ unsigned size = 2; char** args = fmalloc(size * sizeof(*args)); unsigned len = 0; /* Add each argument name to the array */ char* arg = nextToken(expr); if(arg == NULL && **expr != ')') { /* Invalid character */ Value_free(val); free(args); free(name); var = VarErr(badChar(**expr)); return Expression_new(var); } trimSpaces(expr); if(arg == NULL) { /* Empty parameter list means function with no args */ free(args); args = NULL; len = 0; } else { /* Loop through each argument in the list */ while(**expr == ',' || **expr == ')') { args[len++] = arg; if(**expr == ')') break; (*expr)++; /* Expand argument array if it's too small */ if(len >= size) { size *= 2; args = frealloc(args, size * sizeof(*args)); } arg = nextToken(expr); if(arg == NULL) { /* Invalid character */ Value_free(val); free(name); /* Free argument names and return */ unsigned i; for(i = 0; i < len; i++) { free(args[i]); } free(args); var = VarErr(badChar(**expr)); return Expression_new(var); } trimSpaces(expr); } } if(**expr != ')') { /* Invalid character inside argument name list */ Value_free(val); free(name); /* Free argument names and return */ unsigned i; for(i = 0; i < len; i++) { free(args[i]); } free(args); var = VarErr(badChar(**expr)); return Expression_new(var); } /* Skip closing parenthesis */ (*expr)++; trimSpaces(expr); if(**expr != '=') { Value_free(val); free(name); unsigned i; for(i = 0; i < len; i++) { free(args[i]); } free(args); var = VarErr(badChar(**expr)); return Expression_new(var); } /* Construct function and return it */ Function* func = Function_new(len, args, val); var = VarFunc(name, func); free(name); ret = Expression_new(var); } else { /* Defining a variable */ if(**expr != '=') { /* In-place manipulation */ BINTYPE bin = BinOp_nextType(expr, 0, 0); /* Still not an equals sign means invalid character */ if(**expr != '=') { Value_free(val); free(name); var = VarErr(badChar(**expr)); return Expression_new(var); } val = ValExpr(BinOp_new(bin, ValVar(name), val)); } var = VarValue(name, val); free(name); ret = Expression_new(var); } return ret; }