%{ #include #include #include #include #include #include #include "type.h" #include "ir.h" #include "y.tab.h" int yylex(void); int lineno=1; static enum state { SOP, STERM, SPTR } state = STERM; static bool asm_mode = false; __attribute__((format (printf, 1, 2))) void pdebug(const char *format, ...); #define RETS(val_) RETS_S(val_, yytext) #define RETS_S(val_, str_) do {pdebug(#val_ ": %s\n", (str_)); yylval.id = strdup((str_)); return (val_);} while (0) #define RET_TYPE(val_, ty_) do {pdebug(#val_ ": %s (" #ty_ ")\n", yytext); yylval.type = ty_; return (val_);} while (0) #define RET_INSTYPE(val_, it_) do {pdebug(#val_ ": " #it_ "\n"); yylval.instype = (it_); return (val_);} while (0) #define RET_REF(val_, r_) do {pdebug(#val_ ": " #r_ "\n"); yylval.ref = (r_); return (val_);} while (0) #define RET(val_) do {pdebug(#val_ "\n"); return val_;} while (0) %} %option noinput nounput LETTER [a-zA-Z] DIGIT [0-9] ID {LETTER}({LETTER}|{DIGIT}|_)* DIGITS {DIGIT}{DIGIT}* NUM -?{DIGITS} /* An inclusive state; all other rules will still fire */ %s ASM_MODE /* An exclusive state; no other rules will fire */ %x C_COMMENT %% {NUM} { state = SOP; RETS(NUM); } int { state = SPTR; RET_TYPE(INT, type_int(16)); } void { state = SPTR; RET_TYPE(VOID, type_void()); } if { RET(IF); } else { RET(ELSE); } while { RET(WHILE); } for { RET(FOR); } return { state = STERM; RET(RETURN); } asm { asm_mode = true; BEGIN(ASM_MODE); RET(ASM); } {ID} { state = SOP; if (asm_mode) { int len = strlen(yytext); char name[len + 1]; for (int i = 0; i < len; i++) name[i] = tolower(yytext[i]); name[len] = '\0'; if (strcmp(name, "add") == 0) RET_INSTYPE(ASMINS2, INS_ADD); else if (strcmp(name, "sub") == 0) RET_INSTYPE(ASMINS2, INS_SUB); else if (strcmp(name, "mul") == 0) RET_INSTYPE(ASMINS2, INS_MUL); else if (strcmp(name, "div") == 0) RET_INSTYPE(ASMINS2, INS_DIV); else if (strcmp(name, "mod") == 0) RET_INSTYPE(ASMINS2, INS_MOD); else if (strcmp(name, "test") == 0) RET_INSTYPE(ASMINS2, INS_TEST); else if (strcmp(name, "cmp") == 0) RET_INSTYPE(ASMINS2, INS_CMP); else if (strcmp(name, "mov") == 0) RET_INSTYPE(ASMINS2, INS_MOV); else if (strcmp(name, "neg") == 0) RET_INSTYPE(ASMINS1, INS_NEG); else if (strcmp(name, "not") == 0) RET_INSTYPE(ASMINS1, INS_NOT); else if (strcmp(name, "push") == 0) RET_INSTYPE(ASMINS1, INS_PUSH); else if (strcmp(name, "pop") == 0) RET_INSTYPE(ASMINS1, INS_POP); else if (strcmp(name, "hwi") == 0) RET_INSTYPE(ASMINS1, INS_HWI); else if (strcmp(name, "ret") == 0) RET_INSTYPE(ASMINS0, INS_RET); else if (strcmp(name, "brk") == 0) RET_INSTYPE(ASMINS0, INS_BRK); else if (strcmp(name, "jmp") == 0) RET_INSTYPE(ASMINS_NAME, INS_JMP); else if (strcmp(name, "call") == 0) RET_INSTYPE(ASMINS_NAME, INS_CALL); else if (strcmp(name, "a") == 0) RET_REF(ASMREG, ref_reg(REG_A)); else if (strcmp(name, "b") == 0) RET_REF(ASMREG, ref_reg(REG_B)); else if (strcmp(name, "c") == 0) RET_REF(ASMREG, ref_reg(REG_C)); else if (strcmp(name, "d") == 0) RET_REF(ASMREG, ref_reg(REG_D)); else if (strcmp(name, "x") == 0) RET_REF(ASMREG, ref_reg(REG_X)); else if (strcmp(name, "y") == 0) RET_REF(ASMREG, ref_reg(REG_Y)); else if (strcmp(name, "sp") == 0) RET_REF(ASMREG, ref_reg(REG_SP)); else if (strcmp(name, "bp") == 0) RET_REF(ASMREG, ref_reg(REG_BP)); else RETS(ID); } else { RETS(ID); } } [+-] { pdebug("%c in ASM_MODE\n", yytext[0]); return yytext[0]; } @{ID} { pdebug("'%s'\n", yytext); RETS_S(ASMVARNAME, yytext + 1); } "//"[^\n]* {} "/*" { pdebug("C_COMMENT... "); fflush(stdout); BEGIN(C_COMMENT); } "*/" { pdebug("done\n"); BEGIN(INITIAL); } . {} \n { lineno++; if (asm_mode) RET(NEWLINE); } \n { lineno++; if (asm_mode) RET(NEWLINE); } [ \t]+ {} "+" { state = STERM; RETS(ADDOP); } [/%] { state = STERM; RETS(MULOP); } "<"=?|">"=?|==|!= { state = STERM; RETS(RELOP); } &&|"||" { state = STERM; RETS(BOOLOP); } = { state = STERM; RET(ASSIGN); } "!" { state = STERM; RET(NOT); } "-" { switch (state) { case SOP: state = STERM; RETS(ADDOP); case STERM: state = STERM; RET(NEGATE); default: fprintf(stderr, "Unexpected '-'\n"); exit(1); } } "*" { switch (state) { case SOP: state = STERM; RETS(MULOP); case STERM: state = STERM; RET(DEREF); case SPTR: state = SPTR; RET(PTR); default: fprintf(stderr, "Unexpected '*'\n"); exit(1); } } "&" { switch (state) { case SOP: fprintf(stderr, "Bit-and not implemented\n"); exit(1); case STERM: state = STERM; RET(ADDROF); default: fprintf(stderr, "Unexpected '&'\n"); exit(1); } } ")" { state = SOP; pdebug("')'\n"); return ')'; } "}" { state = STERM; pdebug("'}'\n"); asm_mode = false; BEGIN(INITIAL); return '}'; } . { pdebug(".: %c\n", yytext[0]); return yytext[0]; } %% void pdebug(const char *format, ...) { (void)format; #ifdef DEBUG va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); #endif } /* vim:et:ts=4:sw=4 */