Summary Files Commits Branches @commit @diff @stats
path: root / Year 3 / Compilers, Introduction / coolc-spim / my-code / coursework / pa1 / cool.flex
blob: 6db63543aefaf0373ce04247ee2d106dc8183db2 (plain) (blame)
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
/*
 *  The scanner definition for COOL.
 */

%{
#include <cool-parse.h>
#include <stringtab.h>
#include <utilities.h>

/* The compiler assumes these identifiers. */
#define yylval cool_yylval
#define yylex  cool_yylex

/* Max size of string constants */
#define MAX_STR_CONST 1025
#define YY_NO_UNPUT   /* keep g++ happy */

extern FILE *fin; /* we read from this file */

/* define YY_INPUT so we read from the FILE fin:
 * This change makes it possible to use this scanner in
 * the Cool compiler.
 */
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
	if ( (result = fread( (char*)buf, sizeof(char), max_size, fin)) < 0) \
		YY_FATAL_ERROR( "read() in flex scanner failed");

char string_buf[MAX_STR_CONST]; /* to assemble string constants */
char *string_buf_ptr;

extern int curr_lineno;
extern int verbose_flag;

extern YYSTYPE cool_yylval;

/*
 *  Add Your own definitions here
 */

char* escapeString(const char* str) {
	unsigned length = 0;
	for (const char* i = str; *i != '\0'; ++i) {
		if (*i == '\\') ++i;
		if (*i == '\n') curr_lineno++; // this maybe shouldn't be here, but it's fine
		length++;
	}

	char* out = new char[length - 1];
	out[length - 2] = '\0';
	char* currout = out;

	for (const char* i = str + 1; i[1] != '\0'; ++i) {
		if (*i != '\\') *(currout++) = *i;
		else switch (i[1]) {
			case 'b':  *(currout++) = '\b'; ++i; break;
			case 't':  *(currout++) = '\t'; ++i; break;
			case 'n':  *(currout++) = '\n'; ++i; break;
			case 'f':  *(currout++) = '\f'; ++i; break;
			case '\\': *(currout++) = '\\'; ++i; break;
		}
	}

	return out;
}

bool strStarted = false;
unsigned openedComments = 0;

%}

/* 
 * Info from /usr/class/cs143/cool/include/PA2/cool-parse.h
 * Tokens:
 *   STR_CONST CLASS ELSE FI IF IN INHERITS ISVOID LET LOOP POOL THEN WHILE CASE ESAC NEW OF NOT DARROW TYPEID OBJECTID INT_CONST BOOL_CONST ASSIGN LE ERROR
 * yylval types:
 *   Boolean boolean;
 *   Symbol symbol;
 *   char *error_msg;
 */

ALL   (.|\n)
ENDL  \n|\r\n
BLANK [ \f\t\v\r]
IDCHR [A-Za-z0-9_]

%x MULTILINE

%%

--[^\n\r]*               { }
<MULTILINE,INITIAL>\(\*  { openedComments++; BEGIN(MULTILINE); }
<MULTILINE>\*\)          { if (--openedComments == 0) BEGIN(INITIAL); }
<MULTILINE>{ENDL}        { curr_lineno++; }
<MULTILINE>.             { }
<MULTILINE><<EOF>>       { cool_yylval.error_msg = "EOF in comment"; BEGIN(INITIAL); return (ERROR); }

\"([^"\0\n\\]|\\[^\0])*\"  {
	char* str = escapeString(yytext);
	if (strlen(str) >= MAX_STR_CONST) {
		cool_yylval.error_msg = "String constant too long";
		return (ERROR);
	}
	else {
		cool_yylval.symbol = inttable.add_string(str);
		return (STR_CONST); 
	}
}
\"([^"\0\n\\]|\\[^\0])*{ENDL}       { cool_yylval.error_msg = "Unterminated string constant";            curr_lineno++; return (ERROR); }
\"([^"\0\n\\]|\\{ALL})*(\"|{ENDL})  { cool_yylval.error_msg = "String contains escaped null character."; return (ERROR); }
\"([^"\n\\]|\\[^\0])*(\"|{ENDL})    { cool_yylval.error_msg = "String contains null character.";         return (ERROR); }
\"([^"\0\n\\]|\\[^\0])*             { cool_yylval.error_msg = "EOF in string constant";                  return (ERROR); }

\*\)  { cool_yylval.error_msg = "Unmatched *)"; return (ERROR); }

(?i:class)              { return (CLASS); }
(?i:else)               { return (ELSE); }
(?i:fi)                 { return (FI); }
(?i:if)                 { return (IF); }
(?i:in)                 { return (IN); }
(?i:inherits)           { return (INHERITS); }
(?i:isvoid)             { return (ISVOID); }
(?i:let)                { return (LET); }
(?i:loop)               { return (LOOP); }
(?i:pool)               { return (POOL); }
(?i:then)               { return (THEN); }
(?i:while)              { return (WHILE); }
(?i:case)               { return (CASE); }
(?i:esac)               { return (ESAC); }
(?i:new)                { return (NEW); }
(?i:of)                 { return (OF); }
(?i:not)                { return (NOT); }
"=>"                    { return (DARROW); }
"<="                    { return (LE); }
"<-"                    { return (ASSIGN); }
(t(?i:rue)|f(?i:alse))  { cool_yylval.boolean = *yytext == 't'; return (BOOL_CONST); }

[a-z]{IDCHR}*  { cool_yylval.symbol = inttable.add_string(yytext); return (OBJECTID); }
[0-9]+         { cool_yylval.symbol = inttable.add_string(yytext); return (INT_CONST); }
[A-Z]{IDCHR}*  { cool_yylval.symbol = inttable.add_string(yytext); return (TYPEID); }

\{|\}|\(|\)|:|;|,|@|\.|\+|-|\*|\/|~|<|<=|=    { return *yytext; }

{ENDL}   { curr_lineno++; }
{BLANK}  { }
.        { cool_yylval.error_msg = yytext; return (ERROR); }

%%