void block(int pIndex) /* pIndex はこのブロックの関数名のインデックス */ { int backP; backP = genCodeV(jmp, 0); /* 内部関数を飛び越す命令、後でバックパッチ */ while (1) { /* 宣言部のコンパイルを繰り返す */ switch (token.kind){ case Const: /* 定数宣言部のコンパイル */ token = nextToken(); constDecl(); continue; case Var: /* 変数宣言部のコンパイル */ token = nextToken(); varDecl(); continue; case Func: /* 関数宣言部のコンパイル */ token = nextToken(); funcDecl(); continue; default: /* それ以外なら宣言部は終わり */ break; } break; } backPatch(backP); /* 内部関数を飛び越す命令にパッチ */ changeV(pIndex, nextCode()); /* この関数の開始番地を修正 */ genCodeV(ict, frameL()); /* このブロックの実行時の必要記憶域をとる命令 */ statement(); /* このブロックの主文 */ genCodeR(); /* リターン命令 */ blockEnd(); /* ブロックが終ったことをtableに連絡 */ }
void fncDecl_end(void) /* 関数出口処理 */ { backPatch(fncPt->adrs, -localAdrs); /* フレームサイズ後埋(関数先頭はADBR) */ if (last_statement != Return) { /* 関数末尾にreturnがない */ if (IS_MAIN(fncPt)) gencode2(LDI, 0); /* main関数なら戻値設定 */ else if (fncPt->dtTyp != VOID_T) /* 本処理系の独自仕様 */ err_s("本処理系では非void型関数の末尾には単独のreturn文が必要です。"); } backPatch_RET(fncPt->adrs); /* RET命令列へ飛ぶJMPの飛先番地を後埋 */ gencode3(LOD, LOCAL_F, 0); /* 戻番地をオペランドスタックへ */ gencode2(ADBR, localAdrs); /* フレームを解放 */ gencode1(RET); /* 戻り命令 */ }
void set_main(void) /* main関数処理 */ { if (fncPt->dtTyp != INT_T || fncPt->args != 0) /* 型と引数個数の確認 */ err_s("main関数の書式が不正"); backPatch(0, fncPt->adrs); /* 0番地のCALL命令の番地を後埋 */ }
//进行规约的操作 bool LRGramar::doGuiYue(const int ruleNum) { switch(ruleNum) { case R1: //执行进出站等相关操作 if(!doRules(A_NTERMINAL,4)) { return false; } break; case R2: if(!doRules(B_NTERMINAL,3)) { return false; } break; case R3: if(!doRules(C_NTERMINAL,3)) { return false; } break; case R4: if(!doRules(C_NTERMINAL,0)) { return false; } break; case R5: if(!doRules(D_NTERMINAL,1)) { return false; } break; case R6: case R7: if(!doRules(D_NTERMINAL,1)) { return false; } else { } break; case R8: if(!doRules(F_NTERMINAL,3)) { return false; } else { //堆栈是先进先出 int argP = variableBufferPtr--; int resultPtr = variableBufferPtr--; emit("=",variableBuffer[argP]," ",variableBuffer[resultPtr]); } break; case R9: if(!doRules(G_NTERMINAL,2)) { return false; } else { backPatch(trueChainHead,nextq); //回填真链头 } break; case R10: if(!doRules(S_NTERMINAL,2)) { return false; } else { backPatch(falseChain[falseChainPtr--],nextq); } break; case R11: if(!doRules(T_NTERMINAL,3)) { return false; } else { emit("goto","","","0"); backPatch(falseChain[falseChainPtr--],nextq); falseChain[++falseChainPtr] = nextq-1; } break; case R12: if(!doRules(S_NTERMINAL,2)) { return false; } backPatch(falseChain[falseChainPtr--],nextq); break; case R13: if(!doRules(W_NTERMINAL,2)) { return false; } else { backPatch(trueChainHead,doTrue[doTruePtr--]); backPatch(falseChain[falseChainPtr--],nextq); } break; case R14: if(!doRules(K_NTERMINAL,1)) { return false; } doTrue[++doTruePtr] = nextq;//保存do后面的地址 break; case R15: if(!doRules(L_NTERMINAL,2)) { return false; } break; case R16: if(!doRules(N_NTERMINAL,2)) { return false; } break; case R17: if(!doRules(Q_NTERMINAL,3)) { return false; } else { trueChainHead = nextq; falseChain[++falseChainPtr]=nextq+1; char temp[10]; int arg2 = variableBufferPtr--; int arg1 = variableBufferPtr--; sprintf(temp,"%s%s%s",variableBuffer[arg1],lastOp[OpPtr--],variableBuffer[arg2]); emit("if",temp,"goto","0"); emit("goto","","","0"); } break; case R18: if(!doRules(P_NTERMINAL,2)) { return false; } else { if(strcmp(variableBuffer[variableBufferPtr],"null")!=0) { char *pPlace = newTemp(); emit(lastOp[OpPtr--],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],pPlace); strcpy(variableBuffer[++variableBufferPtr],pPlace); } else { variableBufferPtr--; } } break; case R19: if(!doRules(H_NTERMINAL,3)) { return false; } else { if(strcmp(variableBuffer[variableBufferPtr],"null")!=0) { char *hPlace = newTemp(); emit(lastOp[OpPtr--],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],hPlace); strcpy(variableBuffer[++variableBufferPtr],hPlace); } else { variableBufferPtr--; } strcpy(lastOp[++OpPtr],"+"); } break; case R20: if(!doRules(H_NTERMINAL,3)) { return false; } else { if(strcmp(variableBuffer[variableBufferPtr],"null")!=0) { char *hPlace = newTemp(); emit(lastOp[OpPtr--],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],hPlace); strcpy(variableBuffer[++variableBufferPtr],hPlace); } else { variableBufferPtr--; } strcpy(lastOp[++OpPtr],"-"); } break; case R21: if(!doRules(H_NTERMINAL,0)) { return false; } else { strcpy(variableBuffer[++variableBufferPtr],"null"); } break; case R22: if(!doRules(Z_NTERMINAL,2)) { return false; } else { if(strcmp(variableBuffer[variableBufferPtr],"null")!=0) { char *zPlace = newTemp(); emit(lastOp[OpPtr--],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],zPlace); strcpy(variableBuffer[++variableBufferPtr],zPlace); } else { variableBufferPtr--; } } break; case R23: if(!doRules(V_NTERMINAL,3)) { return false; } else { if(strcmp(variableBuffer[variableBufferPtr],"null")!=0) { char *vPlace = newTemp(); emit(lastOp[--OpPtr],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],vPlace); strcpy(variableBuffer[++variableBufferPtr],vPlace); } else { variableBufferPtr--; } strcpy(lastOp[++OpPtr] ,"*"); } break; case R24: if(!doRules(V_NTERMINAL,3)) { return false; } else { if(strcmp(variableBuffer[variableBufferPtr],"null")!=0) { char *vPlace = newTemp(); emit(lastOp[--OpPtr],variableBuffer[variableBufferPtr--],variableBuffer[variableBufferPtr--],vPlace); strcpy(variableBuffer[++variableBufferPtr],vPlace); } else { variableBufferPtr--; } strcpy(lastOp[++OpPtr] ,"/"); } break; case R25: case R26: if(!doRules(U_NTERMINAL,1)) { return false; } break; case R27: if(!doRules(U_NTERMINAL,3)) { return false; } break; case R28: strcpy(lastOp[++OpPtr],"<"); if(!doRules(Y_NTERMINAL,1)) { return false; } break; case R29: if(!doRules(Y_NTERMINAL,1)) { return false; } strcpy(lastOp[++OpPtr],"<="); break; case R30: if(!doRules(Y_NTERMINAL,1)) { return false; } strcpy(lastOp[++OpPtr],">"); break; case R31: if(!doRules(Y_NTERMINAL,1)) { return false; } strcpy(lastOp[++OpPtr],">="); break; case R32: if(!doRules(Y_NTERMINAL,1)) { return false; } strcpy(lastOp[++OpPtr],"=="); break; case R33: if(!doRules(Y_NTERMINAL,1)) { return false; } strcpy(lastOp[++OpPtr],"!="); break; case R34: if(!doRules(V_NTERMINAL,0)) { return false; } else { strcpy(variableBuffer[++variableBufferPtr],"null"); } break; default: return false; } return true; }
void statement(){ int l; int m; symTableEntry* symbol; int tempLabels[2]; if(currentToken == identsym){ symbol = findSymbol(symTable, VAR, tokenVal.string, scope); if(!findVar(tokenVal.string, scope, &l, &m)){ if(findConst(tokenVal.string, scope, &m)) throwError(CANNOT_ASSIGN_TO_CONST_OR_PROC); else throwError(UNDEC_ID); } readToken(); if(currentToken != becomessym) throwError(ASSIGN_EXPEC); readToken(); expression(); genCode(STO, l, m); } else if(currentToken == syawsym){ readToken(); if(currentToken != identsym) throwError(ID_FOLLOW_SYAW); if(!findFunc(tokenVal.string, scope, &l, &m)) throwError(UNDEC_ID); genCode(CAL, l, m); readToken(); } else if(currentToken == sngaisym){ // 'beginsym' readToken(); statement(); while(currentToken == semicolonsym){ readToken(); statement(); } if(currentToken != fpesym && (currentToken != identsym && currentToken != sngaisym && currentToken != txosym && currentToken != tengkrrsym)) // 'endsym' //throwError(WRONG_SYM_AFTER_STATE); throwError(SEMICOL_OR_RBRACK_EXPEC); else if(currentToken == identsym || currentToken == sngaisym || currentToken == txosym || currentToken == tengkrrsym) throwError(SEMICOL_BW_STATE_MISS); readToken(); } else if(currentToken == txosym){ // 'ifsym' tempLabels[1] = 0; readToken(); condition(); tempLabels[0] = reserveCode(); //Conditional jump will go here if(currentToken != tsakrrsym) // 'thensym' throwError(TSAKRR_EXPEC); readToken(); statement(); if(currentToken == txokefyawsym){ tempLabels[1] = reserveCode(); readToken(); } backPatch(tempLabels[0], JPC, 0, genLabel()); if(tempLabels[1]){ statement(); backPatch(tempLabels[1], JMP, 0, genLabel()); } } else if(currentToken == tengkrrsym){ // 'whilesym' readToken(); tempLabels[0] = genLabel(); //Jump back up to here at the end of the loop condition(); tempLabels[1] = reserveCode(); //Stick the conditional jump here if(currentToken != sisym) // 'dosym' throwError(SI_EXPEC); readToken(); statement(); genCode(JMP, 0, tempLabels[0]); backPatch(tempLabels[1], JPC, 0, genLabel()); } else if(currentToken == misym){ // Input genCode(SIO, 0, 2); readToken(); if(currentToken == identsym){ if(findVar(tokenVal.string, scope, &l, &m)) genCode(STO, l, m); else if(findConst(tokenVal.string, scope, &m) || findFunc(tokenVal.string, scope, &l, &m)) throwError(CANNOT_STORE_IN_CONST_OR_PROC); else throwError(UNDEC_ID); readToken(); } } else if(currentToken == wrrpasym){ // Output readToken(); if(currentToken == identsym){ if(findVar(tokenVal.string, scope, &l, &m)) genCode(LOD, l, m); else if(findConst(tokenVal.string, scope, &m)) genCode(LIT, 0, m); else throwError(UNDEC_ID); readToken(); } genCode(SOI, 0, 1); } else if(currentToken == fpesym){ return; } else{ if(currentToken == periodsym) throwError(RBRACK_EXPEC_AT_END); else throwError(STATEMENT_EXPEC); } return; }
void block(){ int jmpLoc = reserveCode(); int thisScope; int numVars = 0; char tempSymbol[MAX_IDENT_LENGTH + 1]; if(currentToken == constsym){ /***************************************************************/ /* const-declaration ::= [ "const" ident "=" number */ /* {"," ident "=" number} ";"] */ /***************************************************************/ do{ readToken(); if(currentToken != identsym){ throwError(ID_FOLLOW_CONST_VAR_PROC); }else{ strcpy(tempSymbol, tokenVal.string); } readToken(); if(currentToken != eqsym){ if(currentToken == becomessym) throwError(EQ_NOT_BECOMES); else throwError(EQ_FOLLOW_ID); } readToken(); if(currentToken != numbersym){ throwError(NUM_FOLLOW_EQ); }else{ insertSymbol(symTable, newSymbol(CONST, tempSymbol, scope, 0, tokenVal.numeric)); } readToken(); }while(currentToken == commasym); if(currentToken != semicolonsym) throwError(SEMICOL_COMMA_MISS); readToken(); } if(currentToken == intsym){ /*******************************************************/ /* var-declaration ::= ["int" ident {"," ident} ";"] */ /*******************************************************/ do{ readToken(); if(currentToken != identsym){ throwError(ID_FOLLOW_CONST_VAR_PROC); }else{ insertSymbol(symTable, newSymbol(VAR, tokenVal.string, scope, BASE_OFFSET + numVars++, 0)); } readToken(); }while(currentToken == commasym); if(currentToken != semicolonsym) throwError(SEMICOL_COMMA_MISS); readToken(); } //Saving the scope before moving into procedure declarations thisScope = scope; while(currentToken == procsym){ /**********************************************************************/ /* proc-declaration ::= {"procedure" ident ";" block ";"} statement */ /**********************************************************************/ readToken(); if(currentToken != identsym) throwError(ID_FOLLOW_CONST_VAR_PROC); //Storing the function name in the symbol table insertSymbol(symTable, newSymbol(FUNC, tokenVal.string, thisScope, genLabel(), 0)); readToken(); if(currentToken != semicolonsym) throwError(SEMICOL_COMMA_MISS); readToken(); //Incrementing the scope for our new function and saving its parent //in the disjoint set scope++; scopeParent[scope] = thisScope; block(); if(currentToken != semicolonsym) throwError(WRONG_SYM_AFTER_PROC); readToken(); } //Restoring the scope scope = thisScope; backPatch(jmpLoc, JMP, 0, genLabel()); genCode(INC, 0, BASE_OFFSET + numVars); statement(); genCode(OPR, 0, RET); return; }
void statement() /* 文のコンパイル */ { int tIndex; KindT k; int backP, backP2; /* バックパッチ用 */ while(1) { switch (token.kind) { case Id: /* 代入文のコンパイル */ tIndex = searchT(token.u.id, varId); /* 左辺の変数のインデックス */ setIdKind(k=kindT(tIndex)); /* 印字のための情報のセット */ if (k != varId && k != parId) /* 変数名かパラメタ名のはず */ errorType("var/par"); token = checkGet(nextToken(), Assign); /* ":="のはず */ expression(); /* 式のコンパイル */ genCodeT(sto, tIndex); /* 左辺への代入命令 */ return; case If: /* if文のコンパイル */ token = nextToken(); condition(); /* 条件式のコンパイル */ token = checkGet(token, Then); /* "then"のはず */ backP = genCodeV(jpc, 0); /* jpc命令 */ statement(); /* 文のコンパイル */ backPatch(backP); /* 上のjpc命令にバックパッチ */ return; case Ret: /* return文のコンパイル */ token = nextToken(); expression(); /* 式のコンパイル */ genCodeR(); /* ret命令 */ return; case Begin: /* begin . . end文のコンパイル */ token = nextToken(); while(1){ statement(); /* 文のコンパイル */ while(1){ if (token.kind==Semicolon){ /* 次が";"なら文が続く */ token = nextToken(); break; } if (token.kind==End){ /* 次がendなら終り */ token = nextToken(); return; } if (isStBeginKey(token)){ /* 次が文の先頭記号なら */ errorInsert(Semicolon); /* ";"を忘れたことにする */ break; } errorDelete(); /* それ以外ならエラーとして読み捨てる */ token = nextToken(); } } case While: /* while文のコンパイル */ token = nextToken(); backP2 = nextCode(); /* while文の最後のjmp命令の飛び先 */ condition(); /* 条件式のコンパイル */ token = checkGet(token, Do); /* "do"のはず */ backP = genCodeV(jpc, 0); /* 条件式が偽のとき飛び出すjpc命令 */ statement(); /* 文のコンパイル */ genCodeV(jmp, backP2); /* while文の先頭へのジャンプ命令 */ backPatch(backP); /* 偽のとき飛び出すjpc命令へのバックパッチ */ return; case Write: /* write文のコンパイル */ token = nextToken(); expression(); /* 式のコンパイル */ genCodeO(wrt); /* その値を出力するwrt命令 */ return; case WriteLn: /* writeln文のコンパイル */ token = nextToken(); genCodeO(wrl); /* 改行を出力するwrl命令 */ return; case End: case Semicolon: /* 空文を読んだことにして終り */ return; default: /* 文の先頭のキーまで読み捨てる */ errorDelete(); /* 今読んだトークンを読み捨てる */ token = nextToken(); continue; } } }