📄 codegen.c
字号:
if (gettoken() != T_LEFTBRACE) { scanerror(T_SEMICOLON, "Missing left brace for initialization list"); (void) tokenmode(oldmode); return -1; } for (index = 0; ; index++) { switch(gettoken()) { case T_COMMA: case T_NEWLINE: continue; case T_RIGHTBRACE: (void) tokenmode(oldmode); return index; case T_LEFTBRACE: rescantoken(); addop(OP_DUPLICATE); addopone(OP_ELEMADDR, index); (void) getinitlist(); break; default: rescantoken(); getopassignment(); } addopone(OP_ELEMINIT, index); switch (gettoken()) { case T_COMMA: case T_NEWLINE: continue; case T_RIGHTBRACE: (void) tokenmode(oldmode); return index; default: scanerror(T_SEMICOLON, "Missing right brace for initialization list"); (void) tokenmode(oldmode); return -1; } }}/* * Get a condition. * condition = '(' assignment ')'. */static voidgetcondition(void){ if (gettoken() != T_LEFTPAREN) { scanerror(T_SEMICOLON, "Missing left parenthesis for condition"); return; } (void) getexprlist(); if (gettoken() != T_RIGHTPAREN) { scanerror(T_SEMICOLON, "Missing right parenthesis for condition"); return; }}/* * Get an expression list consisting of one or more expressions, * separated by commas. The value of the list is that of the final expression. * This is the top level routine for parsing expressions. * Returns flags describing the type of the last assignment or expression found. * exprlist = assignment [ ',' assignment ] ... */static intgetexprlist(void){ int type; type = getopassignment(); while (gettoken() == T_COMMA) { addop(OP_POP); type = getopassignment(); } rescantoken(); return type;}/* * Get an opassignment or possibly just an assignment or expression. * Returns flags describing the type of assignment or expression found. * assignment = lvalue '=' assignment * | lvalue '+=' assignment * | lvalue '-=' assignment * | lvalue '*=' assignment * | lvalue '/=' assignment * | lvalue '%=' assignment * | lvalue '//=' assignment * | lvalue '&=' assignment * | lvalue '|=' assignment * | lvalue '<<=' assignment * | lvalue '>>=' assignment * | lvalue '^=' assignment * | lvalue '**=' assignment * | orcond. */static intgetopassignment(void){ int type; /* type of expression */ long op; /* opcode to generate */ type = getassignment(); switch (gettoken()) { case T_PLUSEQUALS: op = OP_ADD; break; case T_MINUSEQUALS: op = OP_SUB; break; case T_MULTEQUALS: op = OP_MUL; break; case T_DIVEQUALS: op = OP_DIV; break; case T_SLASHSLASHEQUALS: op = OP_QUO; break; case T_MODEQUALS: op = OP_MOD; break; case T_ANDEQUALS: op = OP_AND; break; case T_OREQUALS: op = OP_OR; break; case T_LSHIFTEQUALS: op = OP_LEFTSHIFT; break; case T_RSHIFTEQUALS: op = OP_RIGHTSHIFT; break; case T_POWEREQUALS: op = OP_POWER; break; case T_HASHEQUALS: op = OP_HASHOP; break; case T_TILDEEQUALS: op = OP_XOR; break; case T_BACKSLASHEQUALS: op = OP_SETMINUS; break; default: rescantoken(); return type; } if (isrvalue(type)) { scanerror(T_NULL, "Illegal assignment"); (void) getopassignment(); return (EXPR_RVALUE | EXPR_ASSIGN); } writeindexop(); for(;;) { addop(OP_DUPLICATE); if (gettoken() == T_LEFTBRACE) { rescantoken(); addop(OP_DUPVALUE); getinitlist(); while (gettoken() == T_ASSIGN) getinitlist(); rescantoken(); } else { rescantoken(); (void) getassignment(); } addop(op); addop(OP_ASSIGN); switch (gettoken()) { case T_PLUSEQUALS: op = OP_ADD; break; case T_MINUSEQUALS: op = OP_SUB; break; case T_MULTEQUALS: op = OP_MUL; break; case T_DIVEQUALS: op = OP_DIV; break; case T_SLASHSLASHEQUALS: op = OP_QUO; break; case T_MODEQUALS: op = OP_MOD; break; case T_ANDEQUALS: op = OP_AND; break; case T_OREQUALS: op = OP_OR; break; case T_LSHIFTEQUALS: op = OP_LEFTSHIFT; break; case T_RSHIFTEQUALS: op = OP_RIGHTSHIFT; break; case T_POWEREQUALS: op = OP_POWER; break; case T_HASHEQUALS: op = OP_HASHOP; break; case T_TILDEEQUALS: op = OP_XOR; break; case T_BACKSLASHEQUALS: op = OP_SETMINUS; break; default: rescantoken(); return EXPR_ASSIGN; } }}/* * Get an assignment (lvalue = ...) or possibly just an expression */static intgetassignment (void){ int type; /* type of expression */ switch(gettoken()) { case T_COMMA: case T_SEMICOLON: case T_NEWLINE: case T_RIGHTPAREN: case T_RIGHTBRACKET: case T_RIGHTBRACE: case T_EOF: addop(OP_UNDEF); rescantoken(); return EXPR_RVALUE; } rescantoken(); type = getaltcond(); switch (gettoken()) { case T_NUMBER: case T_IMAGINARY: addopone(OP_NUMBER, tokennumber()); type = (EXPR_RVALUE | EXPR_CONST); /*FALLTHRU*/ case T_STRING: case T_SYMBOL: case T_OLDVALUE: case T_LEFTPAREN: case T_PLUSPLUS: case T_MINUSMINUS: case T_NOT: scanerror(T_NULL, "Missing operator"); return type; case T_ASSIGN: break; default: rescantoken(); return type; } if (isrvalue(type)) { scanerror(T_SEMICOLON, "Illegal assignment"); (void) getassignment(); return (EXPR_RVALUE | EXPR_ASSIGN); } writeindexop(); if (gettoken() == T_LEFTBRACE) { rescantoken(); getinitlist(); while (gettoken() == T_ASSIGN) getinitlist(); rescantoken(); return EXPR_ASSIGN; } rescantoken(); (void) getassignment(); addop(OP_ASSIGN); return EXPR_ASSIGN;}/* * Get a possible conditional result expression (question mark). * Flags are returned indicating the type of expression found. * altcond = orcond [ '?' orcond ':' altcond ]. */static intgetaltcond(void){ int type; /* type of expression */ LABEL donelab; /* label for done */ LABEL altlab; /* label for alternate expression */ type = getorcond(); if (gettoken() != T_QUESTIONMARK) { rescantoken(); return type; } clearlabel(&donelab); clearlabel(&altlab); addoplabel(OP_JUMPZ, &altlab); type = getaltcond(); if (gettoken() != T_COLON) { scanerror(T_SEMICOLON, "Missing colon for conditional expression"); return EXPR_RVALUE; } addoplabel(OP_JUMP, &donelab); setlabel(&altlab); type |= getaltcond(); setlabel(&donelab); return type;}/* * Get a possible conditional or expression. * Flags are returned indicating the type of expression found. * orcond = andcond [ '||' andcond ] ... */static intgetorcond(void){ int type; /* type of expression */ LABEL donelab; /* label for done */ clearlabel(&donelab); type = getandcond(); while (gettoken() == T_OROR) { addoplabel(OP_CONDORJUMP, &donelab); type |= getandcond(); } rescantoken(); if (donelab.l_chain >= 0) setlabel(&donelab); return type;}/* * Get a possible conditional and expression. * Flags are returned indicating the type of expression found. * andcond = relation [ '&&' relation ] ... */static intgetandcond(void){ int type; /* type of expression */ LABEL donelab; /* label for done */ clearlabel(&donelab); type = getrelation(); while (gettoken() == T_ANDAND) { addoplabel(OP_CONDANDJUMP, &donelab); type |= getrelation(); } rescantoken(); if (donelab.l_chain >= 0) setlabel(&donelab); return type;}/* * Get a possible relation (equality or inequality), or just an expression. * Flags are returned indicating the type of relation found. * relation = sum '==' sum * | sum '!=' sum * | sum '<=' sum * | sum '>=' sum * | sum '<' sum * | sum '>' sum * | sum. */static intgetrelation(void){ int type; /* type of expression */ long op; /* opcode to generate */ type = getsum(); switch (gettoken()) { case T_EQ: op = OP_EQ; break; case T_NE: op = OP_NE; break; case T_LT: op = OP_LT; break; case T_GT: op = OP_GT; break; case T_LE: op = OP_LE; break; case T_GE: op = OP_GE; break; default: rescantoken(); return type; } if (islvalue(type)) addop(OP_GETVALUE); (void) getsum(); addop(op); return EXPR_RVALUE;}/* * Get an expression made up of sums of products. * Flags indicating the type of expression found are returned. * sum = product [ {'+' | '-'} product ] ... */static intgetsum(void){ int type; /* type of expression found */ long op; /* opcode to generate */ type = EXPR_RVALUE; switch(gettoken()) { case T_PLUS: (void) getproduct(); addop(OP_PLUS); break; case T_MINUS: (void) getproduct(); addop(OP_NEGATE); break; default: rescantoken(); type = getproduct(); } for (;;) { switch (gettoken()) { case T_PLUS: op = OP_ADD; break; case T_MINUS: op = OP_SUB; break; case T_HASH: op = OP_HASHOP; break; default: rescantoken(); return type; } if (islvalue(type)) addop(OP_GETVALUE); (void) getproduct(); addop(op); type = EXPR_RVALUE; }}/* * Get the product of arithmetic or expressions. * Flags indicating the type of expression found are returned. * product = orexpr [ {'*' | '/' | '//' | '%'} orexpr ] ... */static intgetproduct(void){ int type; /* type of value found */ long op; /* opcode to generate */ type = getorexpr(); for (;;) { switch (gettoken()) { case T_MULT: op = OP_MUL; break; case T_DIV: op = OP_DIV; break; case T_MOD: op = OP_MOD; break; case T_SLASHSLASH: op = OP_QUO; break; default: rescantoken(); return type; } if (islvalue(type)) addop(OP_GETVALUE); (void) getorexpr(); addop(op); type = EXPR_RVALUE; }}/* * Get an expression made up of arithmetic or operators. * Flags indicating the type of expression found are returned. * orexpr = andexpr [ '|' andexpr ] ... */static intgetorexpr(void){ int type; /* type of value found */ type = getandexpr(); while (gettoken() == T_OR) { if (islvalue(type)) addop(OP_GETVALUE); (void) getandexpr(); addop(OP_OR); type = EXPR_RVALUE; } rescantoken(); return type;}/* * Get an expression made up of arithmetic and operators. * Flags indicating the type of expression found are returned. * andexpr = shiftexpr [ '&' shiftexpr ] ... */static intgetandexpr(void){ int type; /* type of value found */ long op; type = getshiftexpr(); for (;;) { switch (gettoken()) { case T_AND: op = OP_AND; break; case T_TILDE: op = OP_XOR; break; case T_BACKSLASH: op = OP_SETMINUS; break; default: rescantoken(); return type; } if (islvalue(type)) addop(OP_GETVALUE); (void) getshiftexpr(); addop(op); type = EXPR_RVALUE; }}/* * Get a shift or power expression. * Flags indicating the type of expression found are returned. * shift = '+' shift * | '-' shift * | '/' shift * | '\' shift * | '~' shift * | '#' shift * | reference '^' shiftexpr * | reference '<<' shiftexpr * | reference '>>' shiftexpr * | reference. */static intgetshiftexpr(void){ int type; /* type of value found */ long op; /* opcode to generate */ op = 0; switch (gettoken()) { case T_PLUS: op = OP_PLUS; break; case T_MINUS: op = OP_NEGATE; break; case T_NOT: op = OP_NOT; break; case T_DIV: op = OP_INVERT; break; case T_BACKSLASH: op = OP_BACKSLASH; break; case T_TILDE: op = OP_COMP; break; case T_HASH: op = OP_CONTENT; break; } if (op) { (void) getshiftexpr(); addop(op); return EXPR_RVALUE; } rescantoken(); type = getreference(); switch (gettoken()) { case T_POWER: op = OP_POWER; break; case T_LEFTSHIFT: op = OP_LEFTSHIFT; break; case T_RIGHTSHIFT: op = OP_RIGHTSHIFT; break; default: rescantoken(); return type; } if (islvalue(type)) addop(OP_GETVALUE); (void) getshiftexpr(); addop(op); return EXPR_RVALUE;}/* * set an address or dereference indicator * address = '&' term * dereference = '*' term */static intgetreference(void){ int type; switch(gettoken()) { case T_ANDAND: scanerror(T_NULL, "&& used as prefix operator"); /*FALLTHRU*/ case T_AND: type = getreference(); addop(OP_PTR); type = EXPR_RVALUE; break; case T_MULT: (void) getreference(); addop(OP_DEREF); type = 0; break; case T_POWER: /* '**' or '^' */ (void) getreference(); addop(OP_DEREF); addop(OP_DEREF); type = 0; break; default: rescantoken(); type = getincdecexpr(); } return type;}/* * get an increment or decrement expression * ++expr, --expr, expr++, expr-- */static intgetincdecexpr(void){ int type; int tok; type = getterm(); tok = gettoken(); if (tok == T_PLUSPLUS || tok == T_MINUSMINUS) { if (isrvalue(type)) scanerror(T_NULL, "Bad ++ usage"); writeindexop(); if (tok == T_PLUSPLUS) addop(OP_POSTINC); else addop(OP_POSTDEC); for (;;) { tok = gettoken(); switch(tok) { case T_PLUSPLUS: addop(OP_PREINC); continue; case T_MINUSMINUS: addop(OP_PREDEC); continue; default: addop(OP_POP); break; } break; } type = EXPR_RVALUE | EXPR_ASSIGN; } if (tok == T_NOT) { addopfunction(OP_CALL, getbuiltinfunc("fact"), 1); tok = gettoken(); type = EXPR_RVALUE; } rescantoken(); return type;}/* * Get a single term. * Flags indicating the type of value found are returned. * term = lvalue * | lvalue '[' assignment ']' * | lvalue '++' * | lvalue '--' * | real_number * | imaginary_number * | '.' * | string * | '(' assignment ')' * | function [ '(' [assignment [',' assignment] ] ')' ] * | '!' term */static intgetterm(void){ int type; /* type of term found */ int oldmode; type = 0; switch (gettoken()) { case T_NUMBER: addopone(OP_NUMBER, tokennumber()); type = (EXPR_RVALUE | EXPR_CONST); break; case T_IMAGINARY: addopone(OP_IMAGINARY, tokennumber()); type = (EXPR_RVALUE | EXPR_CONST); break; case T_OLDVALUE: addop(OP_OLDVALUE); type = 0; break; case T_STRING: addopone(OP_STRING, tokenstring()); type = EXPR_RVALUE; break; case T_PLUSPLUS: if (isrvalue(getterm())) scanerror(T_NULL, "Bad ++ usage"); writeindexop(); addop(OP_PREINC); type = EXPR_ASSIGN; break; case T_MINUSMINUS: if (isrvalue(getterm())) scanerror(T_NULL, "Bad -- usage"); writeindexop(); addop(OP_PREDEC); type = EXPR_ASSIGN; break; case T_LEFTPAREN: oldmode = tokenmode(TM_DEFAULT); type = getexprlist(); if (gettoken() != T_RIGHTPAREN) scanerror(T_SEMICOLON, "Missing right parenthesis"); (void) tokenmode(oldmode); break; case T_MAT: getonematrix(SYM_UNDEFINED); type = EXPR_ASSIGN; break; case T_OBJ:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -