aboutsummaryrefslogtreecommitdiff
path: root/c.l
diff options
context:
space:
mode:
Diffstat (limited to 'c.l')
-rw-r--r--c.l69
1 files changed, 60 insertions, 9 deletions
diff --git a/c.l b/c.l
index 77381fb..4bac236 100644
--- a/c.l
+++ b/c.l
@@ -2,13 +2,14 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
+#include <ctype.h>
#include "type.h"
+#include "ir.h"
#include "y.tab.h"
-#undef DEBUG
-
int yylex(void);
int lineno=1;
@@ -19,12 +20,17 @@ static enum state {
SPTR
} state = STERM;
+static bool asm_mode = false;
+
__attribute__((format (printf, 1, 2)))
void pdebug(const char *format, ...);
-#define RETS(val_) {pdebug(#val_ ": %s\n", yytext); yylval.id = strdup(yytext); return val_;}
-#define RET_TYPE(val_, ty_) {pdebug(#val_ ": %s (" #ty_ ")\n", yytext); yylval.type = ty_; return val_;}
-#define RET(val_) {pdebug(#val_ "\n"); return val_;}
+#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)
%}
@@ -37,6 +43,9 @@ 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
@@ -51,17 +60,57 @@ 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);
+ }
+ }
-{ID} { state = SOP; RETS(ID); }
+<ASM_MODE>[+-] { pdebug("%c in ASM_MODE\n", yytext[0]); return yytext[0]; }
+<ASM_MODE>@{ID} { pdebug("'%s'\n", yytext); RETS_S(ASMVARNAME, yytext + 1); }
"//"[^\n]* {}
"/*" { pdebug("C_COMMENT... "); fflush(stdout); BEGIN(C_COMMENT); }
<C_COMMENT>"*/" { pdebug("done\n"); BEGIN(INITIAL); }
<C_COMMENT>. {}
-<C_COMMENT>\n { lineno++; }
+<C_COMMENT>\n { lineno++; if (asm_mode) RET(NEWLINE); }
-\n { lineno++; }
+\n { lineno++; if (asm_mode) RET(NEWLINE); }
[ \t]+ {}
"+" { state = STERM; RETS(ADDOP); }
@@ -74,7 +123,7 @@ return { state = STERM; RET(RETURN); }
"-" {
switch (state) {
case SOP: state = STERM; RETS(ADDOP);
- case STERM: state = STERM; RETS(NEGATE);
+ case STERM: state = STERM; RET(NEGATE);
default: fprintf(stderr, "Unexpected '-'\n"); exit(1);
}
}
@@ -98,6 +147,8 @@ return { state = STERM; RET(RETURN); }
")" { state = SOP; pdebug("')'\n"); return ')'; }
+"}" { state = STERM; pdebug("'}'\n"); asm_mode = false; BEGIN(INITIAL); return '}'; }
+
. { pdebug(".: %c\n", yytext[0]); return yytext[0]; }