-
Notifications
You must be signed in to change notification settings - Fork 14
/
asmlex.l
167 lines (141 loc) · 3.51 KB
/
asmlex.l
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
D [0-9]
L [a-z]
U [A-Z]
A [A-Za-z]
AN [A-Za-z0-9]
AU [A-Za-z_]
ANU [A-Za-z0-9_]
%{
#define YY_SKIP_YYWRAP
#define yylex asmlex
#define yywrap() (1)
void yyerror(char*);
//#define YYSTYPE long long int
//extern YYSTYPE yylval;
#include "y.tab.h"
#include <stdlib.h>
#define BISON
#include "scmd_tok.c"
#include "regname_tok.c"
#define USE_STRDUP
#ifdef USE_STRDUP
#define STRDUP(X) strdup(X)
#else
#define STRDUP(X) (X)
#endif
#define IRET(X) do{yylval.i = X; return X;}while(0)
#define SRET(X) do{yylval.s = STRDUP(yytext); return X;}while(0)
#define NRET(X) do{yylval.i = atoi(yytext); return X;}while(0)
/* XXX */
YYSTYPE yylval;
const char *yyfilename;
int yyfatalerrors;
%}
%%
\"([^\n"\\]|\\['"?\\abfnrtv]|\\[0-7]{1,3}|\\[Xx][0-9a-fA-F]+)*\" SRET(STRING);
[\t ]+ ;
[#;].*\n { /* ignore comments */ goto newline; }
\n { newline:; ++yylineno; return 10; }
"label"{ANU}+ SRET(LABEL);
{AU}{ANU}*"$"{D}+ |
{AU}{ANU}*"::"{ANU}+"$"{D}+ { SRET(FN_I); }
{AU}{ANU}*("::"{ANU}+)?"^"{D}+ |
{AU}{ANU}*"::"{ANU}+ { SRET(FN_E); }
-?{D}+ { NRET(NUMBER);}
{AU}{ANU}* SRET(ID);
[=:@,\.\[\]] return yytext[0];
. { yyerror("unknown character/token"); }
%%
static int section = 0;
static int ltok = 0;
static int last_mnemonic = 0;
#undef yylex
int yylex() {
int ret = asmlex();
if(ret == '\n') {
ltok = 0;
return ret;
} else if (ltok==0 && ret == '.') goto set_section;
switch(section) {
case 0: if(ret != '.') yyerror("expected section start symbol '.'!");
set_section:
ret = asmlex();
if(ret != ID) yyerror("expected section name!");
if(!strcmp(yytext, "data")) section = SECTION_DATA;
else if(!strcmp(yytext, "text")) section = SECTION_TEXT;
else if(!strcmp(yytext, "imports")) section = SECTION_IMPORTS;
else if(!strcmp(yytext, "exports")) section = SECTION_EXPORTS;
else if(!strcmp(yytext, "strings")) section = SECTION_STRINGS;
else if(!strcmp(yytext, "sections")) section = SECTION_SECTIONS;
else if(!strcmp(yytext, "fixups")) section = SECTION_FIXUPS;
if(!section) yyerror("unknown section name!");
return section;
case SECTION_DATA:
/* FIXME variable names here can't be one of the 4 keywords */
if (ret == ID) {
if(!strcmp(yytext, "export")) IRET(D_EXPORT);
else if(!strcmp(yytext, "int")) IRET(D_INT);
else if(!strcmp(yytext, "short")) IRET(D_SHORT);
else if(!strcmp(yytext, "char")) IRET(D_CHAR);
}
break;
case SECTION_TEXT:
if(ret == ',') break;
++ltok;
if (ret == ID) {
if (ltok == 1) {
int tmp;
if((tmp = KW_SCMD_find_keyword(yytext, yyleng)))
{
last_mnemonic = tok2scmd(tmp);
IRET(tmp);
}
} else {
const struct opcode_info *i = &opcodes[last_mnemonic];
if(i->regcount >= ltok-1) {
int tmp;
if((tmp = RN_find_keyword(yytext, yyleng)))
IRET(tmp);
}
}
return ID;
} else if (ret == LABEL) {
/* user may haven chosen a variable name matching a label */
if(ltok == 1 || last_mnemonic == SCMD_JMP ||
last_mnemonic == SCMD_JZ || last_mnemonic == SCMD_JNZ)
return ret;
return ID;
}
}
return ret;
}
void yyerror(char *s) {
printf("%s:%d %s at `%s`\n",
yyfilename==0?"stdin":yyfilename,
yylineno,
s,
yytext[0] == 10 ? "<newline>" : yytext);
if(yyfatalerrors) abort();
}
void yylex_reset(FILE *f, const char *fn) {
yyfilename = fn;
yylineno = 1;
#ifdef YY_FLUSH_BUFFER
YY_FLUSH_BUFFER;
#endif
yyin = f;
if(yytext) yytext[0] = 0;
section = 0;
ltok = 0;
last_mnemonic = 0;
}
#ifdef LDEBUG
int main() {
while(1) {
int n = yylex();
if(n == EOF) break;
printf("%d\n", n);
if(feof(yyin)) break;
}
}
#endif