Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 6

/*

* The scanner definition for COOL.


*/

/*
* Stuff enclosed in %{ %} in the first section is copied verbatim to the
* output, so headers and global definitions are placed here to be visible
* to the code in the file. Don't remove anything that was here initially
*/
%option noyywrap
%{
#include <cool-parse.h>
#include <stringtab.h>
#include <utilities.h>
#include <cstring>

/* 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=string_buf;

extern int curr_lineno;


extern int verbose_flag;

extern YYSTYPE cool_yylval;

/*
* Add Your own definitions here
*/
int comment_brackets_counter = 0;
int string_len = 0;

void resetBuffer();
void addToStr(char* character);
bool str_too_long();

%}

/*
* Define names for regular expressions here.
*/
DARROW =>
DIGIT [0-9]
ALPHANUMERIC [a-zA-Z0-9_]
TYPEID [A-Z]{ALPHANUMERIC}*
OBJECTID [a-z]{ALPHANUMERIC}*
WHITE_SPACE [ \f\r\t\v]
LE <=
ASSIGN <-

%x STRING
%x COMMENT_BRACKETS
%x COMMENT_DASH
%x AFTER_STRING_TOO_LONG

%%

\n {curr_lineno++;}

_[{ALPHANUMERIC}]* { /*ne triba vise*/


cool_yylval.error_msg = "_";
BEGIN(INITIAL);
return (ERROR);
}

{WHITE_SPACE} { }

"(*" {
comment_brackets_counter++;
BEGIN(COMMENT_BRACKETS);
}

<COMMENT_BRACKETS>{
"*)" {
comment_brackets_counter--;
if (comment_brackets_counter == 0){
BEGIN(INITIAL);
}
}

"(*" { comment_brackets_counter++; }

"\n" { curr_lineno++; }

. { }

<<EOF>> {
cool_yylval.error_msg = "EOF in comment";
BEGIN(INITIAL);
return (ERROR);
}
}

"*)" {
cool_yylval.error_msg = "Unmatched *)";
BEGIN(INITIAL);
return (ERROR);
}
"--" {
BEGIN(COMMENT_DASH);
}

<COMMENT_DASH>{
. {}
\n {
curr_lineno++;
BEGIN(INITIAL);
}
}

{DARROW} { return (DARROW); }


{LE} { return (LE); }
{ASSIGN} { return (ASSIGN); }

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

[cC][lL][aA][sS][sS] { return (CLASS); }


[eE][lL][sS][eE] { return (ELSE);}
[f][aA][lL][sS][eE] { cool_yylval.boolean = 0; return (BOOL_CONST);}
[fF][iI] { return (FI); }
[iI][fF] { return (IF); }
[iI][nN] { return (IN); }
[iI][nN][hH][eE][rR][iI][tT][sS] { return (INHERITS); }
[iI][sS][vV][oO][iI][dD] { return (ISVOID); }
[lL][eE][tT] { return (LET); }
[lL][oO][oO][pP] { return (LOOP); }
[pP][oO][oO][lL] { return (POOL); }
[tT][hH][eE][nN] { return (THEN); }
[wW][hH][iI][lL][eE] { return (WHILE); }
[cC][aA][sS][eE] { return (CASE); }
[eE][sS][aA][cC] { return (ESAC); }
[nN][eE][wW] { return (NEW); }
[oO][fF] { return (OF); }
[nN][oO][tT] { return (NOT); }
[t][rR][uU][eE] { cool_yylval.boolean = 1; return (BOOL_CONST);}

{OBJECTID} {
cool_yylval.symbol = stringtable.add_string(yytext);
return (OBJECTID);
}

{TYPEID} {
cool_yylval.symbol = stringtable.add_string(yytext);
return (TYPEID);
}

{DIGIT}+ {
cool_yylval.symbol = stringtable.add_string(yytext);
return (INT_CONST);
}

\" {
string_len = 0;
string_buf_ptr=string_buf;
BEGIN(STRING);
}

<STRING>{
\" {
/*zatvaramo string, triba spremit sve procitano i ispraznit buffer i
postavit duljinu na 0*/
cool_yylval.symbol = stringtable.add_string(string_buf);
resetBuffer();
BEGIN(INITIAL);
return (STR_CONST);
}

\0 {
cool_yylval.error_msg = "String contains null character";
resetBuffer();
BEGIN(INITIAL);
return ERROR;
}

\n {
cool_yylval.error_msg = "Unterminated string constant";
curr_lineno++;
resetBuffer();
BEGIN(INITIAL);
return (ERROR);
}

\\n {
if(str_too_long()){
return (ERROR);
}
addToStr("\n");
}
\\\n {
if(str_too_long()){
return (ERROR);
}
addToStr("\n");
}
\\b {
if(str_too_long()){
return (ERROR);
}
addToStr("\b");
}

\\t {
if(str_too_long()){
return (ERROR);
}
addToStr("\t");
}

\\f {
if(str_too_long()){
return (ERROR);
}
addToStr("\f");
}
\\0 { /*Ovo nan zapravo ne triba jer ga skupi pravilo ispod*/
if(str_too_long()){
return (ERROR);
}
addToStr("0");
}

\\. { /* Escape-amo \, tj. ovaj drugi je sad samo znak \ nema neko posebno
znacenje,
* Prvi znak predstavlja escape znak
* Drugi znak \ je zapravo prvi koji ce bit u yytext[0]
* . je bilo koji znak iza toga koji je spremljen u yytext[1]
*/
if(str_too_long())
{
/* ako se nakon pogreške pojavi ASCII znak nove linije, onda je to kraj
stringa
* ako se nakon pogreške, a prije ASCII znaka nove linije pojavi znak ”
onda je to kraj stringa -> pribaceno u funkciju
*/
return (ERROR);
}
addToStr(&yytext[1]);
}

. {
if(str_too_long()){
return (ERROR);
}
addToStr(&yytext[0]);
}

<<EOF>> {
cool_yylval.error_msg = "EOF in string constant";
curr_lineno++;
BEGIN(INITIAL);
return ERROR;
}

<AFTER_STRING_TOO_LONG>{
\" {BEGIN(INITIAL);}
\n { curr_lineno++; BEGIN(INITIAL);}
. {}
}

. {
cool_yylval.error_msg = yytext;
return ERROR;
}

%%
void addToStr(char* character){
*string_buf_ptr = *character;
string_buf_ptr++;
string_len++;
}

void resetBuffer() {
memset(string_buf, '\0', MAX_STR_CONST);
string_buf_ptr = string_buf;
string_len = 0;
}

bool str_too_long(){
if(string_len >= MAX_STR_CONST -1){
cool_yylval.error_msg = "String constant too long";
resetBuffer();
BEGIN (AFTER_STRING_TOO_LONG);
return true;
}

return false;
}

You might also like