TXT
TXT
TXT
/*
* 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>
/*
* 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++;}
{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);
}
}
{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;
}