Exemple #1
0
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);
}
Exemple #2
0
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);
    }
}
Exemple #3
0
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);
}
Exemple #4
0
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();
}
Exemple #5
0
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");
}
Exemple #6
0
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;
    }
}
Exemple #7
0
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;
        }
    }
}
Exemple #8
0
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;
}