Skip to content

Instantly share code, notes, and snippets.

@ghaiklor
Created December 16, 2019 19:22
Show Gist options
  • Save ghaiklor/f705d586bc13563b232256218a8a64b7 to your computer and use it in GitHub Desktop.
Save ghaiklor/f705d586bc13563b232256218a8a64b7 to your computer and use it in GitHub Desktop.
Flex specification for COOL language
%{
#include <cool-parse.h>
#include <stringtab.h>
#include <utilities.h>
#include <string.h>
#define yylval cool_yylval
#define yylex cool_yylex
#define MAX_STR_CONST 1025
#define YY_NO_UNPUT /* keep g++ happy */
extern FILE *fin; /* we read from this file */
#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;
int comment_depth = 0;
%}
%option yylineno
%x COMMENT
%x STRING
%x STRING_ERROR
NEWLINE \n
WHITESPACE [ \n\f\r\t\v]
ONELINE_COMMENT "--"(.*)
CLASS (?i:class)
ELSE (?i:else)
FI (?i:fi)
IF (?i:if)
IN (?i:in)
INHERITS (?i:inherits)
ISVOID (?i:isvoid)
LET (?i:let)
LOOP (?i:loop)
POOL (?i:pool)
THEN (?i:then)
WHILE (?i:while)
CASE (?i:case)
ESAC (?i:esac)
NEW (?i:new)
OF (?i:of)
NOT (?i:not)
FALSE "f"(?i:alse)
TRUE "t"(?i:rue)
DARROW =>
ASSIGN <-
LE <=
INTEGER [0-9]+
TYPE_ID [A-Z][a-zA-Z0-9_]*
OBJECT_ID [a-z][a-zA-Z0-9_]*
SYMBOLS [\(\)\{\}\=\<\~\@\/\*\-\+\:\;\.\,]
%%
<INITIAL>{
"(*" { BEGIN(COMMENT); comment_depth++; }
"*)" { curr_lineno = yylineno; cool_yylval.error_msg = "Unmatched *)"; return (ERROR); }
"\"" { strcpy(string_buf, ""); BEGIN(STRING); }
}
<COMMENT>{
<<EOF>> { curr_lineno = yylineno; cool_yylval.error_msg = "EOF in comment"; BEGIN(INITIAL); return (ERROR); }
"(*" { comment_depth++; }
"*)" { comment_depth--; if (comment_depth == 0) { BEGIN(INITIAL); } }
\n { curr_lineno = yylineno; }
. { curr_lineno = yylineno; }
}
<STRING>{
\\\x00 {
curr_lineno = yylineno;
cool_yylval.error_msg = "String contains escaped null character.";
BEGIN(STRING_ERROR);
return (ERROR);
}
\\. {
int len = strlen(string_buf);
curr_lineno = yylineno;
if ((len + 1 + 1) > MAX_STR_CONST) {
cool_yylval.error_msg = "String constant too long";
BEGIN(STRING_ERROR);
return (ERROR);
}
if (yytext[1] == 'b') { string_buf[len] = '\b'; } else
if (yytext[1] == 't') { string_buf[len] = '\t'; } else
if (yytext[1] == 'n') { string_buf[len] = '\n'; } else
if (yytext[1] == 'f') { string_buf[len] = '\f'; } else
{ string_buf[len] = yytext[1]; }
string_buf[len + 1] = '\0';
}
\" {
curr_lineno = yylineno;
cool_yylval.symbol = stringtable.add_string(string_buf);
BEGIN(INITIAL);
return (STR_CONST);
}
\x00 {
curr_lineno = yylineno;
cool_yylval.error_msg = "String contains null character";
BEGIN(STRING_ERROR);
return (ERROR);
}
\\\n {
int len = strlen(string_buf);
if ((len + 1 + 1) > MAX_STR_CONST) {
cool_yylval.error_msg = "String constant too long";
BEGIN(STRING_ERROR);
return (ERROR);
}
string_buf[len] = '\n';
string_buf[len + 1] = '\0';
curr_lineno = yylineno;
}
\n {
curr_lineno = yylineno;
cool_yylval.error_msg = "Unterminated string constant";
BEGIN(INITIAL);
return (ERROR);
}
<<EOF>> {
curr_lineno = yylineno;
cool_yylval.error_msg = "EOF in string constant";
BEGIN(INITIAL);
return (ERROR);
}
[^\\\"\x00\n]+ {
curr_lineno = yylineno;
if ((strlen(string_buf) + strlen(yytext) + 1) > MAX_STR_CONST) {
cool_yylval.error_msg = "String constant too long";
BEGIN(STRING_ERROR);
return (ERROR);
}
strcat(string_buf, yytext);
}
}
<STRING_ERROR>{
([\"]|[^\\]\n) { curr_lineno = yylineno; BEGIN(INITIAL); }
. { /* DO NOTHING */ }
}
{NEWLINE} { }
{WHITESPACE} { }
{ONELINE_COMMENT} { curr_lineno = yylineno; }
{CLASS} { curr_lineno = yylineno; return (CLASS); }
{ELSE} { curr_lineno = yylineno; return (ELSE); }
{FI} { curr_lineno = yylineno; return (FI); }
{IF} { curr_lineno = yylineno; return (IF); }
{IN} { curr_lineno = yylineno; return (IN); }
{INHERITS} { curr_lineno = yylineno; return (INHERITS); }
{ISVOID} { curr_lineno = yylineno; return (ISVOID); }
{LET} { curr_lineno = yylineno; return (LET); }
{LOOP} { curr_lineno = yylineno; return (LOOP); }
{POOL} { curr_lineno = yylineno; return (POOL); }
{THEN} { curr_lineno = yylineno; return (THEN); }
{WHILE} { curr_lineno = yylineno; return (WHILE); }
{CASE} { curr_lineno = yylineno; return (CASE); }
{ESAC} { curr_lineno = yylineno; return (ESAC); }
{NEW} { curr_lineno = yylineno; return (NEW); }
{OF} { curr_lineno = yylineno; return (OF); }
{NOT} { curr_lineno = yylineno; return (NOT); }
{DARROW} { curr_lineno = yylineno; return (DARROW); }
{ASSIGN} { curr_lineno = yylineno; return (ASSIGN); }
{LE} { curr_lineno = yylineno; return (LE); }
{FALSE} {
cool_yylval.boolean = false;
curr_lineno = yylineno;
return (BOOL_CONST);
}
{TRUE} {
cool_yylval.boolean = true;
curr_lineno = yylineno;
return (BOOL_CONST);
}
{INTEGER} {
cool_yylval.symbol = inttable.add_string(yytext);
curr_lineno = yylineno;
return (INT_CONST);
}
{TYPE_ID} {
cool_yylval.symbol = idtable.add_string(yytext);
curr_lineno = yylineno;
return (TYPEID);
}
{OBJECT_ID} {
cool_yylval.symbol = idtable.add_string(yytext);
curr_lineno = yylineno;
return (OBJECTID);
}
{SYMBOLS} {
curr_lineno = yylineno;
return (yytext[0]);
}
. {
curr_lineno = yylineno;
cool_yylval.error_msg = yytext;
return (ERROR);
}
%%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment