void Parser::whileStat() { consume(TK_while); int pos1 = emitHole(); int pos2 = HERE; Value a = expr(syms->localsTop()); Vector<int> copyExp; Vector<int> &code = proto->code; while (code.size() > pos2) { copyExp.push(code.pop()); } block(); emitJump(pos1, JMP, UNUSED, HERE); while (copyExp.size()) { code.push(copyExp.pop()); } emitJump(HERE, JT, a, pos2); }
void Parser::ifStat() { consume(TK_if); Value a = expr(syms->localsTop()); int pos1 = emitHole(); block(); if (lexer->token == TK_else) { int pos2 = emitHole(); emitJump(pos1, JF, a, HERE); consume(TK_else); if (lexer->token == '{') { block(); } else { ifStat(); } emitJump(pos2, JMP, UNUSED, HERE); } else { emitJump(pos1, JF, a, HERE); } }
void Parser::forStat() { consume(TK_for); syms->enterBlock(false); CERR(TOKEN != TK_NAME, E_FOR_NAME, VNIL); Value name = lexer->info.name; int slot = syms->localsTop(); advance(); consume(':'+TK_EQUAL); patchOrEmitMove(slot+2, slot+2, expr(slot+2)); consume(':'); patchOrEmitMove(slot+3, slot+1, expr(slot+3)); int pos1 = emitHole(); int pos2 = HERE; syms->set(name, slot); syms->addLocalsTop(2); insideBlock(); emitJump(HERE, LOOP, VAL_REG(slot), pos2); emitJump(pos1, FOR, VAL_REG(slot), HERE); syms->exitBlock(false); }
void DFABytecodeCompiler::compileNode(unsigned index) { const DFANode& node = m_dfa.nodeAt(index); // Record starting index for linking. m_nodeStartOffsets[index] = m_bytecode.size(); for (uint64_t action : node.actions) emitAppendAction(static_cast<unsigned>(action)); for (const auto& transition : node.transitions) emitCheckValue(transition.key, transition.value); if (node.hasFallbackTransition) emitJump(node.fallbackTransition); else emitTerminate(); }
void codeGen(Node *root, FILE *ucoFile) { Node *p; // pointer for Node int globalSize; // the size of global variables file = ucoFile; // rootTable = initSymbolTable(); // step 1: process the declaration part for (p = root->son; p; p = p->next) { if (p->token.tokenNumber == DCL) { processDeclaration(rootTable, p->son); } else if (p->token.tokenNumber == FUNC_DEF) { processFuncHeader(rootTable, p->son); } else { icg_error(3); } } globalSize = rootTable->offset - 1; // step 2: process the function part for (p = root->son; p; p = p->next) { if (p->token.tokenNumber == FUNC_DEF) { processFunction(rootTable, p); } } display(rootTable, 0); // step 3: generate codes for starting routine // bgn globalSize // ldp // call main // end emit1("bgn", globalSize); emit0("ldp"); emitJump("call", "main"); emit0("end"); }
void processStatement(SymbolTable *table, Node *ptr) { Node *p; char label1[LABEL_SIZE]={0}, label2[LABEL_SIZE]={0}; switch(ptr->token.tokenNumber) { case COMPOUND_ST: p = ptr->son->next; p = p->son; while (p) { processStatement(table, p); p = p->next; } break; case EXP_ST: if (ptr->son != NULL) { processOperator(table, ptr->son); } break; case RETURN_ST: if (ptr->son != NULL) { p = ptr->son; if (p->noderep == NONTERM) { processOperator(table, p); } else { rv_emit(table, p); } emit0("retv"); } else emit0("ret"); flag_returned=1; break; case IF_ST: genLabel(label1); processCondition(table, ptr->son); emitJump("fjp", label1); processStatement(table, ptr->son->next); emitLabel(label1); break; case IF_ELSE_ST: genLabel(label1); genLabel(label2); processCondition(table, ptr->son); emitJump("fjp", label1); processStatement(table, ptr->son->next); emitJump("ujp", label2); emitLabel(label1); processStatement(table, ptr->son->next->next); emitLabel(label2); break; case WHILE_ST: genLabel(label1); genLabel(label2); emitLabel(label1); processCondition(table, ptr->son); emitJump("fjp", label2); processStatement(table, ptr->son->next); emitJump("ujp", label1); emitLabel(label2); break; default: fprintf(file, "not yet implemented.\n"); break; } }
void processOperator(SymbolTable *table, Node *ptr) { int stIndex; switch(ptr->token.tokenNumber) { case ASSIGN_OP: { Node *lhs = ptr->son, *rhs = ptr->son->next; if (lhs->noderep == NONTERM) { lvalue = 1; processOperator(table, lhs); lvalue = 0; } if (rhs->noderep == NONTERM) { processOperator(table, rhs); } else { rv_emit(table, rhs); } if (lhs->noderep == TERMINAL) { stIndex = lookup(table, lhs->token.tokenValue); if (stIndex == -1) { fprintf(stderr, "undefined variable: %s\n", lhs->token.tokenValue); return; } emit2("str", table->rows[stIndex].base, table->rows[stIndex].offset); } else { emit0("sti"); } break; } case ADD_ASSIGN: case SUB_ASSIGN: case MUL_ASSIGN: case DIV_ASSIGN: case MOD_ASSIGN: { Node *lhs = ptr->son, *rhs = ptr->son->next; int nodeNumber = ptr->token.tokenNumber; ptr->token.tokenNumber = ASSIGN_OP; if (lhs->noderep == NONTERM) { lvalue = 1; processOperator(table, lhs); lvalue = 0; } ptr->token.tokenNumber = nodeNumber; if (lhs->noderep == NONTERM) { processOperator(table, lhs); } else { rv_emit(table, lhs); } if (rhs->noderep == NONTERM) { processOperator(table, rhs); } else { rv_emit(table, rhs); } switch(ptr->token.tokenNumber) { case ADD_ASSIGN: emit0("add"); break; case SUB_ASSIGN: emit0("sub"); break; case MUL_ASSIGN: emit0("mult"); break; case DIV_ASSIGN: emit0("div"); break; case MOD_ASSIGN: emit0("mod"); break; } if (lhs->noderep == TERMINAL) { stIndex = lookup(table, lhs->token.tokenValue); if (stIndex == -1) { fprintf(file, "undefined variable: %s\n", lhs->son->token.tokenValue); return; } emit2("str", table->rows[stIndex].base, table->rows[stIndex].offset); } else { emit0("sti"); } break; } case ADD: case SUB: case MUL: case DIV: case MOD: case EQ: case NE: case GT: case LT: case GE: case LE: case LOGICAL_AND: case LOGICAL_OR: { Node *lhs = ptr->son, *rhs = ptr->son->next; if (lhs->noderep == NONTERM) { processOperator(table, lhs); } else { rv_emit(table, lhs); } if (rhs->noderep == NONTERM) { processOperator(table, rhs); } else { rv_emit(table, rhs); } switch(ptr->token.tokenNumber) { case ADD: emit0("add"); break; case SUB: emit0("sub"); break; case MUL: emit0("mult"); break; case DIV: emit0("div"); break; case MOD: emit0("mod"); break; case EQ: emit0("eq"); break; case NE: emit0("ne"); break; case GT: emit0("gt"); break; case LT: emit0("lt"); break; case GE: emit0("ge"); break; case LE: emit0("le"); break; case LOGICAL_AND: emit0("and"); break; case LOGICAL_OR: emit0("or"); break; } break; } case UNARY_MINUS: case LOGICAL_NOT: { Node *p = ptr->son; if (p->noderep == NONTERM) { processOperator(table, p); } else { rv_emit(table, p); } switch(ptr->token.tokenNumber) { case UNARY_MINUS: emit0("neg"); break; case LOGICAL_NOT: emit0("not"); break; } break; } case INDEX: { Node *indexExp = ptr->son->next; if (indexExp->noderep == NONTERM) processOperator(table, indexExp); else rv_emit(table, indexExp); stIndex = lookup(table, ptr->son->token.tokenValue); if (stIndex == -1) { fprintf(file, "undefined variable: %s\n", ptr->son->token.tokenValue); return; } emit2("lda", table->rows[stIndex].base, table->rows[stIndex].offset); emit0("add"); if (!lvalue) { emit0("ldi"); } break; } case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC: { Node *p = ptr->son; Node *q; int stIndex; int amount = 1; if (p->noderep == NONTERM) { processOperator(table, p); } else { rv_emit(table, p); } q = p; while (q->noderep != TERMINAL) { q = q->son; } if (!q || (q->token.tokenNumber != IDENT)) { fprintf(file, "increment/decrement operators can not be applied in expression\n"); return; } stIndex = lookup(table, q->token.tokenValue); if (stIndex == -1) { return; } switch(ptr->token.tokenNumber) { case PRE_INC: emit0("inc"); break; case PRE_DEC: emit0("dec"); break; case POST_INC: emit0("inc"); break; case POST_DEC: emit0("dec"); break; } if (p->noderep == TERMINAL) { stIndex = lookup(table, p->token.tokenValue); if (stIndex == -1) { return; } emit2("str", table->rows[stIndex].base, table->rows[stIndex].offset); } else if (p->token.tokenNumber == INDEX) { lvalue = 1; processOperator(table, p); lvalue = 0; emit0("swp"); emit0("sti"); } else fprintf(file, "error in increment/decrement operators\n"); break; } case CALL: { Node *p = ptr->son; char *functionName; int stIndex; int noArguments; if (checkPredefined(table, p)) { break; } functionName = p->token.tokenValue; stIndex = lookup(rootTable, functionName); if (stIndex == -1) { fprintf(file, "%s: undefined function\n", functionName); break; } noArguments = rootTable->rows[stIndex].width; emit0("ldp"); p = p->next->son; while (p) { if (p->noderep == NONTERM) { processOperator(table, p); } else { rv_emit(table, p); } noArguments--; p = p->next; } if (noArguments > 0) { fprintf(file, "%s: too few actual arguments\n", functionName); } if (noArguments < 0) { fprintf(file, "%s: too many actual arguments\n", functionName); } emitJump("call", ptr->son->token.tokenValue); break; } } }
int checkPredefined(SymbolTable *table, Node *ptr) { Node *p=ptr; char *functionName; int noArguments; int stIndex; functionName = p->token.tokenValue; if (strcmp(functionName, "read") == 0) { noArguments = 1; emit0("ldp"); p = p->next->son; while (p) { if (p->noderep == NONTERM) { processOperator(table, p); } else { stIndex = lookup(table, p->token.tokenValue); if (stIndex == -1) { return 0; } emit2("lda", table->rows[stIndex].base, table->rows[stIndex].offset); } noArguments--; p = p->next; } if (noArguments > 0) { fprintf(file, "%s: too few actual arguments\n", functionName); } if (noArguments < 0) { fprintf(file, "%s: too many actual arguments\n", functionName); } emitJump("call", functionName); return 1; } else if (strcmp(functionName, "write") == 0) { noArguments = 1; emit0("ldp"); p = p->next->son; while (p) { if (p->noderep == NONTERM) { processOperator(table, p); } else { stIndex = lookup(table, p->token.tokenValue); if (stIndex == -1) return 0; emit2("lod", table->rows[stIndex].base, table->rows[stIndex].offset); } noArguments--; p=p->next; } if (noArguments > 0) { fprintf(file, "%s: too few actual arguments\n", functionName); } if (noArguments < 0) { fprintf(file, "%s: too many actual arguments\n", functionName); } emitJump("call", functionName); return 1; } else if (strcmp(functionName, "lf") == 0) { emitJump("call", functionName); return 1; } return 0; }