tChyba TERM2() { int analyza; TItem *pt2; TItem *pt; bool nasel = false; //TERM2->( DRUH TERM2 if(token.stav == s_leva_zavorka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } if(token.stav == s_cele_cislo || token.stav == s_desetinne_cislo || token.stav == s_logicka_hodnota || token.stav == s_string || token.stav == s_identifikator) { analyza = DRUH(); if(analyza != S_BEZ_CHYB) { return analyza; }//pokud nejsme v definici funkce, pridej do nove vznikleho ramce zadany argument if(byla_funkce == false) { int ret = addArgument(token.data); if( ret != S_BEZ_CHYB ){ return ret; } } //vyhledani volane funkce pt = htSearch(ptrhtGlobal, porovnani); //vyhledani funkce, ve ktere se vola funkce pt2 = htSearch(ptrhtGlobal, funkce); if(token.stav == s_identifikator) { //pokud to bylo id if(pt != NULL) { for (int i = 0; i < pt2->data->param.numParam; ++i){ //prochazime pole parametru if(!strcmp(token.data, pt2->data->param.param[i])) { //pokud najdeme parametr tak nastavime na true if(pt->data->param.typeParam[i] != pt2->data->param.typeParam[i]) { //kontrolujeme jestli datove typy parametru jsou stejne return S_SEMANTICKA_CHYBA_TYPOVA; } nasel = true; break; } } if(nasel != true) { //POKUD NENI PARAMETR PROJDEME pt2 = searchFrames(token.data, ptrhtLocal, ptrhtGlobal); if(pt2 != NULL) { //kontrola datovych typu parametru funkce a argumentu if(pt->data->param.typeParam[pocitadlo] != pt2->type) { return S_SEMANTICKA_CHYBA_TYPOVA; } } else { return S_SEMANTICKA_CHYBA_NEDEF; } } } else { return S_SEMANTICKA_CHYBA_NEDEF; } nasel = false; } else { if(pt != NULL) { if(token.stav != pt->data->param.typeParam[pocitadlo]) { return S_SEMANTICKA_CHYBA_TYPOVA; } } else { return S_SEMANTICKA_CHYBA_NEDEF; } } token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } pocitadlo++; return TERM2(); } } //TERM2->, DRUH TERM2 else if(token.stav == s_carka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //pridani argumentu do vznikle tabulky if(byla_funkce == false) { int ret = addArgument(token.data); if( ret != S_BEZ_CHYB ){ return ret; } } if(token.stav == s_cele_cislo || token.stav == s_desetinne_cislo || token.stav == s_logicka_hodnota || token.stav == s_string || token.stav == s_identifikator) { analyza = DRUH(); if(analyza != S_BEZ_CHYB) { return analyza; } //vyhledani volane funkce pt = htSearch(ptrhtGlobal, porovnani); //vyhledani funkce, ve ktere se vola funkce pt2 = htSearch(ptrhtGlobal, funkce); if(token.stav == s_identifikator) { if(pt != NULL) { for (int i = 0; i < pt2->data->param.numParam; ++i){ if(!strcmp(token.data, pt2->data->param.param[i])) { //kontrola zda souhlasi datove typy parametru 2 funkci if(pt->data->param.typeParam[i] != pt2->data->param.typeParam[i]) { return S_SEMANTICKA_CHYBA_TYPOVA; } nasel = true; break; } } //pokud to neni parametr, kontrola jestli je id v tabulkach if(nasel != true) { pt2 = searchFrames(token.data, ptrhtLocal, ptrhtGlobal); if(pt2 != NULL) { if(pt->data->param.typeParam[pocitadlo] != pt2->type) { return S_SEMANTICKA_CHYBA_TYPOVA; } } else { return S_SEMANTICKA_CHYBA_NEDEF; } } } else { return S_SEMANTICKA_CHYBA_NEDEF; } nasel = false; } else {//kontrola datovych typu if(token.stav != pt->data->param.typeParam[pocitadlo]) { return S_SEMANTICKA_CHYBA_TYPOVA; } } } token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } pocitadlo++; return TERM2(); } else if(token.stav == s_prava_zavorka) { pt = htSearch(ptrhtGlobal, porovnani); //zjistime, zda pocet zadanych parametru odpovida poctu parametru pri deklaraci funkce if(pocitadlo != pt->data->param.numParam) { return S_SEMANTICKA_CHYBA_TYPOVA; } if(byla_funkce == true) {//pokud jsme v definici funkce //generovani instrukce fake call generateInstruction(OC_COLL, htSearch(ptrhtGlobal, porovnani ), NULL, NULL ); generateInstruction(OC_NEPRIRAZENI, NULL, NULL, NULL ); } else{ //vygenerovani instrukci InsertFirst for (int i = 0; i < MAX_HTSIZE; ++i){ if( (*ptrhtLocal)[i] ){ if( (*ptrhtLocal)[i]->druh == ID_FUNCTION ){ generateCopyInstr(OC_CPY, (*ptrhtLocal)[i], NULL, NULL ); } } } //predchozi list instrukci, protoze se volal push listIntrukci = &(ptrStack->top->lower->field); //htPrintTable(ptrhtGlobal); //param CALL, Funkce v GLOBALCE, NULL, NAVRATOVKA generateInstruction(OC_CALL, htSearch(ptrhtGlobal, porovnani ), NULL, htSearch( ptrhtLocal, porovnani ) ); //PRIRAZ, NAVRATOVKA, NULL, IDCKO generateInstruction(OC_PRIRAZENI, htSearch( ptrhtLocal, porovnani ), NULL, searchFrames( id, ptrhtLastLocal, ptrhtGlobal ) ); //nastaveni spravneho listu instrukci listIntrukci = &(ptrStack->top->field); //instrukce return na konci volane fce generateInstruction(OC_RET, NULL, NULL, NULL ); } //globalni promenna -> musime nulovat pocitadlo = 0; token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return S_BEZ_CHYB; } return S_SYNTAKTICKA_CHYBA; }
tChyba TERM() { int analyza; TItem *pt, *pt2; //TERM->( DRUH TERM if(token.stav == s_leva_zavorka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } if(token.stav == s_cele_cislo || token.stav == s_desetinne_cislo || token.stav == s_logicka_hodnota || token.stav == s_string || token.stav == s_identifikator) { analyza = DRUH(); if(analyza != S_BEZ_CHYB) { return analyza; } if(token.stav == s_identifikator) { //pokud jsme v definici funkce if(byla_funkce == true) { pt = searchFrames(funkce, ptrhtLocal, ptrhtGlobal); if(pt != NULL) { //kontrolujeme, zda zadany argument je parametr funkce for (int i = 0; i < pt->data->param.numParam; ++i){ if(!strcmp(token.data, pt->data->param.param[i])){ break; } } } } //zjistime, zda id je v nejake tabulce pt2 = searchFrames(token.data, ptrhtLocal, ptrhtGlobal); if(pt2 == NULL) { return S_SEMANTICKA_CHYBA_NEDEF; } //generovani instrukce write generateInstruction( OC_WRITE, pt2 , NULL, NULL ); } else{//pokud neni id, ale primo hodnota TItem *str = (TItem*)malloc(sizeof(TItem)); str->druh = PRINTSTR; str->type = TYPESTR; str->init = true; str->data = (TData*)malloc(sizeof(TData)); str->data->str = allocString(token.data); //jako nahore generateInstruction( OC_WRITE, str , NULL, NULL ); } token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return TERM(); } } //TERM->, DRUH TERM else if(token.stav == s_carka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } if(token.stav == s_cele_cislo || token.stav == s_desetinne_cislo || token.stav == s_logicka_hodnota || token.stav == s_string || token.stav == s_identifikator) { analyza = DRUH(); if(analyza != S_BEZ_CHYB) { return analyza; } if(token.stav == s_identifikator) { //pokud jsme v definici funkce hledej i na parametry, jinak je ve "funkce" nic. if(byla_funkce == true) { pt = searchFrames(funkce, ptrhtLocal, ptrhtGlobal); if(pt != NULL) { for (int i = 0; i < pt->data->param.numParam; ++i){ if(!strcmp(token.data, pt->data->param.param[i])){ break; } } } } pt2 = searchFrames(token.data, ptrhtLocal, ptrhtGlobal); if(pt2 == NULL) { return S_SEMANTICKA_CHYBA_NEDEF; }//generovani instrukce write generateInstruction( OC_WRITE, pt2 , NULL, NULL ); } else{//pokud je argument hodnota TItem *str = (TItem*)malloc(sizeof(TItem)); str->druh = PRINTSTR; str->init = true; str->type = TYPESTR; str->data = (TData*)malloc(sizeof(TData)); str->data->str = allocString(token.data); generateInstruction( OC_WRITE, str , NULL, NULL ); } token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return TERM(); } } else if(token.stav == s_prava_zavorka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return S_BEZ_CHYB; } return S_SYNTAKTICKA_CHYBA; }
// 3, 4, 6, 8 .. tokens static inline void reduce_handle_function(THandle handle) { int num_of_commas = 0; ExprToken *temp = handle.first; if ((++temp)->token->type != TT_leftBrace) { setError(ERR_Reduction); return; } temp++; Symbol *id = SymbolFind(mainContext, handle.first->token->str.data); Context *context = id->funCont; return_value_data_type = (DataType) context->returnType; for (int32_t i = 0; i < context->argCount; i++) // check arguments { if (temp->E.data_type != context->arg[i]->type) { setError(ERR_TypeCompatibilityArg); return; } if (i != context->argCount - 1 && (++temp)->token->type != TT_comma) { setError(ERR_ArgCount); return; } temp++; } // check the end of handle if ((temp)->token->type != TT_rightBrace || temp != handle.last) { setError(ERR_Reduction); return; } // reserve place for return value b.var_type = CONST; // for pushing initialized flag b.initialized = false; a.offset = MY_OFFSET++; generateInstruction(PUSH, &a, &b, &c); // b = pushed operand if (id->index >= 0) // normal functions { for (int32_t i = 0; i < context->argCount; i++) // push arguments in reversed order { temp--; b = temp->E; b.initialized = true; a.offset = MY_OFFSET++; generateInstruction(PUSH, &a, &b, &c); // b = pushed operand, a = local dst temp--; } } else // built-in functions { for (int32_t i = 0; i < context->argCount; i++) // push arguments in reversed order { temp--; b = temp->E; b.initialized = true; a.offset = MY_OFFSET++; generateInstruction(PUSHX, &a, &b, &c); // b = pushed operand, a = local dst temp--; } } if (id->stateFunc == FS_Declared) int64_tVectorAppend(id->adressVector, tape->used); a.offset = id->index; c.offset = MY_OFFSET - 1; // generate CALL instruction switch (a.offset) { case -1: generateInstruction(CALL_LENGTH, &a, &b, &c); break; case -2: generateInstruction(CALL_COPY, &a, &b, &c); break; case -3: generateInstruction(CALL_FIND, &a, &b, &c); break; case -4: generateInstruction(CALL_SORT, &a, &b, &c); break; default: b.int_ = context->locCount; generateInstruction(CALL, &a, &b, &c); break; } // reducing tokenvector MY_OFFSET -= context->argCount; handle.first->handle_start = false; handle.first->type = NONTERM; handle.first->E.data_type = return_value_data_type; handle.first->E.var_type = LOCAL; handle.first->E.offset = MY_OFFSET - 1; if (context->argCount > 1) num_of_commas = context->argCount - 1; ExprTokenVectorPopMore(handle.expr_vector, context->argCount + 2 + num_of_commas); }
tChyba ACT_LIST() { int analyza; int dtype2=0; TItem *pt; //ACT_LIST->end if(!strcmp(token.data, "end") && token.stav == s_klicove) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return S_BEZ_CHYB; } //ACT_LIST->begin ACT_LIST else if(!strcmp(token.data, "begin") && token.stav == s_klicove) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return ACT_LIST(); } //ACT_LIST->id LEXEM ROZHODNI UKONCOVACI else if(token.stav == s_identifikator) { if((id = malloc(strlen(token.data)+1)) == NULL) { return S_INTERNI_CHYBA; } //kopirovani z token.data do globalni strcpy(id, token.data); token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } analyza = LEXEM(); if(analyza != S_BEZ_CHYB) { return analyza; } //pokud se jedna o deklaraci id, dojde k ulozeni jeho datoveho typu if(!strcmp(token.data, "integer")) { dtype2 = TYPEINT; } else if(!strcmp(token.data, "string")) { dtype2 = TYPESTR; } else if(!strcmp(token.data, "real")) { dtype2 = TYPEDOUBLE; } else if(!strcmp(token.data, "boolean")) { dtype2 = TYPEBOOL; } //pokud je prirazeni zkontroluj ze je v nejake tabulce if(prirovnani == true) { pt = searchFrames(id, ptrhtGlobal, ptrhtLocal); if(pt != NULL) { prirovnani = false; } else { return S_SEMANTICKA_CHYBA_NEDEF; } } analyza = ROZHODNI(); if(analyza != S_BEZ_CHYB) { return analyza; } //pokud byla deklarace, ulozime id do lokalniho ramce if(dtype2 != 0) { htDeclInsert(ptrhtLocal,id, dtype2, ID_LOCAL); free(id); } analyza = UKONCOVACI(); if(analyza != S_BEZ_CHYB) { return analyza; } return S_BEZ_CHYB; } else if(!strcmp(token.data, "var") && token.stav == s_klicove) { //ACT_LIST->var id : DTYPE ; ACT_LIST token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } if(token.stav == s_identifikator) { if((id = malloc(strlen(token.data)+1)) == NULL) { return S_INTERNI_CHYBA; } //nesmi se id jmenovat stejne jak tyto funkce if(!strcmp(token.data, "length") || !strcmp(token.data, "copy")) { return S_SEMANTICKA_CHYBA_NEDEF; } //pokud j*z nazev existuje -> chyba pt = searchFrames(token.data, ptrhtLocal, ptrhtGlobal); if(pt != NULL) { return S_SEMANTICKA_CHYBA_NEDEF; } strcpy(id, token.data); token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } else if(token.stav == s_dvojtecka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } analyza = DTYPE(); if(analyza != S_BEZ_CHYB) { return analyza; } if(!strcmp(token.data, "integer")) { dtype = TYPEINT; } else if(!strcmp(token.data, "string")) { dtype = TYPESTR; } else if(!strcmp(token.data, "real")) { dtype = TYPEDOUBLE; } else if(!strcmp(token.data, "boolean")) { dtype = TYPEBOOL; } //vlozeni id do lokalniho ramce htDeclInsert(ptrhtLocal,id, dtype, ID_LOCAL); free(id); token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } else if(token.stav == s_strednik) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } return ACT_LIST(); } } } return S_SYNTAKTICKA_CHYBA; } //ACT_LIST->if EXPR then CYKLUS else CYKLUS UKONCOVACI else if(!strcmp(token.data, "if") && token.stav == s_klicove) { //inkrementace labelu -> vime kolik je vnorenych ifu v sobe lab++; //vlozeni hodnoty lab do TItem data TItem *tmp = (TItem*)malloc(sizeof(TItem)); tmp->type = TYPEINT; tmp->init = true; tmp->data = (TData*)malloc(sizeof(TData)); tmp->data->intNumber = lab; token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //po if nasleduje vyraz, zavolame precedencni na vyhodnoceni analyza = precedencniSA(); if(analyza != S_BEZ_CHYB) { return analyza; } //generovani skoku, tmp1 je logicka hodnota, tmp3 je lab generateInstruction(OC_GOTO, searchFrames(neterminal.polozkaTS.key, ptrhtLocal, ptrhtGlobal), NULL, tmp ); if(!strcmp(token.data, "then") && token.stav == s_klicove) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } analyza = CYKLUS(); if(analyza != S_BEZ_CHYB) { return analyza; } //generovani skoku za else generateInstruction(OC_GOTOAFTER, searchFrames(neterminal.polozkaTS.key, ptrhtLocal, ptrhtGlobal), NULL, tmp ); if(!strcmp(token.data, "else") && token.stav == s_klicove) { //generovani navesti skok do else generateInstruction(OC_ELSE, NULL, NULL, tmp); token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } analyza = CYKLUS(); if(analyza != S_BEZ_CHYB) { return analyza; } //generovani navesti skok za else generateInstruction(OC_AFTER_ELSE, NULL, NULL, tmp); lab--; return UKONCOVACI(); } return S_SYNTAKTICKA_CHYBA; } return S_SYNTAKTICKA_CHYBA; } //ACT_LIST->while EXPR do CYKLUS UKONCOVACI else if(!strcmp(token.data, "while") && token.stav == s_klicove) { //opet na zjisteni jak moc jsme zanoreni lab_while++; TItem *tmp = (TItem*)malloc(sizeof(TItem)); tmp->type = TYPEINT; tmp->init = true; tmp->data = (TData*)malloc(sizeof(TData)); tmp->data->intNumber = lab_while; token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } //generovani navesti skok pred vyhodnoceni podminky generateInstruction(OC_WHILE_PRED, NULL, NULL, tmp); analyza = precedencniSA(); if(analyza != S_BEZ_CHYB) { return analyza; } //generovani skoku, tmp1 je logicka hodnota, tmp3 je lab generateInstruction(OC_GOTO_WHILE, searchFrames(neterminal.polozkaTS.key, ptrhtLocal, ptrhtGlobal), NULL, tmp ); if(!strcmp(token.data, "do") && token.stav == s_klicove) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } analyza = CYKLUS(); if(analyza != S_BEZ_CHYB) { return analyza; } //generovani skoku zpet na zacatek generateInstruction(OC_GOTO_WHILE, searchFrames(neterminal.polozkaTS.key, ptrhtLocal, ptrhtGlobal), NULL, tmp ); //navesti pro skonceni cyklu generateInstruction(OC_WHILE_AFTER, NULL, NULL, tmp); lab_while--; return UKONCOVACI(); } return S_SYNTAKTICKA_CHYBA; } //ACT_LIST->readln ( id ) UKONCOVACI else if(!strcmp(token.data, "readln") && token.stav == s_klicove) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } if(token.stav == s_leva_zavorka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } else if(token.stav == s_identifikator) { //pokud zadany parametr nebyl deklarovan -> chyba pt = searchFrames(token.data, ptrhtLocal, ptrhtGlobal); if(pt == NULL) { return S_SEMANTICKA_CHYBA_NEDEF; } //pokud je datovy typ parametru boolean -> chyba if(pt->type == TYPEBOOL) { return S_SEMANTICKA_CHYBA_TYPOVA; } //generovani instrukce read, v token.data je id generateInstruction(OC_READ, NULL, NULL, searchFrames(token.data,ptrhtLocal,ptrhtGlobal)); token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } else if(token.stav == s_prava_zavorka) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } analyza = UKONCOVACI(); if(analyza != S_BEZ_CHYB) { return analyza; } return S_BEZ_CHYB; } } else { return S_SEMANTICKA_CHYBA_TYPOVA; } } return S_SYNTAKTICKA_CHYBA; } //ACT_LIST->write TERM UKONCOVACI else if(!strcmp(token.data, "write") && token.stav == s_klicove) { token = getNextToken(); if(token.stav == s_lex_error) { return S_LEXIKALNI_CHYBA; } analyza = TERM(); if(analyza != S_BEZ_CHYB) { return analyza; } analyza = UKONCOVACI(); if(analyza != S_BEZ_CHYB) { return analyza; } return S_BEZ_CHYB; } return S_SYNTAKTICKA_CHYBA; }
DataType expr() { int action; instr_counter = 0; bool end_of_eval = true; return_value_data_type = EXPR_ERROR; assert(activeContext); if (activeContext == mainContext) MY_OFFSET = activeContext->locCount + 1; else MY_OFFSET = activeContext->locCount + 2; token++; if(token->type != TT_leftBrace && token->type != TT_not && token->type != TT_minus && !(token->type >= TT_identifier && token->type <= TT_bool)) { setError(ERR_SyntaxExpr); return EXPR_ERROR; } ExprTokenVector *expr_token_vector = ExprTokenVectorInit(32); assert(tokenVector); convert_to_ExprToken(TokenVectorLast(tokenVector), expr_token_vector); // add $ to expr. stack ExprTokenVectorAppend(expr_token_vector, temp_expr_token); // first token, (empty = $) // [$, , , , , ] while (end_of_eval) { convert_to_ExprToken(token, expr_token_vector); if(getError()) { ExprTokenVectorFree(expr_token_vector); return EXPR_ERROR; } AFTER_REDUCE: action = precedence(expr_token_vector); /* vypisy */ //static const char *actions[] = {"shift", "reduce", "handle", "error"}; //ExprTokenVectorPrint(expr_token_vector); //fprintf(stderr, " %s\n", actions[action]); switch(action) { case ERROR: if (top_most_term->token->type == TT_empty && token_to_index(temp_expr_token.token) == TT_empty && expr_token_vector->used != 3) { end_of_eval = false; break; } setError(ERR_PrecedenceTable); ExprTokenVectorFree(expr_token_vector); return EXPR_ERROR; case SHIFT: ExprTokenVectorAppend(expr_token_vector, temp_expr_token); if (top_most_term != ExprTokenVectorLast(expr_token_vector)) top_most_term[1].handle_start = true; break; case HANDLE: ExprTokenVectorAppend(expr_token_vector, temp_expr_token); break; case REDUCE: reduce(expr_token_vector); if(getError()) { ExprTokenVectorFree(expr_token_vector); return EXPR_ERROR; } goto AFTER_REDUCE; break; } if (token_to_index(token) != TT_empty) token++; } /*for (int i = TT_unaryMinus; i <= TT_inequality; i++) { printf("%d\n", i); print_type_table(i); }*/ Instruction *last = InstructionVectorLast(tape); if (instr_counter == 0) { b = (++top_most_term)->E; b.initialized = true; a.offset = MY_OFFSET++; //fprintf(stderr,"EXPR_PUSH a.offset = %ld b.var_type = %d b.offset= %ld b.data_type= %d\n",a.offset,b.var_type,b.offset,b.data_type); generateInstruction(PUSH, &a, &b, &c); // b = pushed operand, a = local dst } else if (last->instr == Instr_CALL) { b.var_type = LOCAL; b.data_type = return_value_data_type; b.offset = MY_OFFSET - 1; a.offset = MY_OFFSET - 1; generateInstruction(PUSH, &a, &b, &c); // b = pushed operand, a = local dst } ExprTokenVectorFree(expr_token_vector); return return_value_data_type; }