Skip to content
Snippets Groups Projects
scanner.l 3.69 KiB
Newer Older
Clemens Paumgarten's avatar
Clemens Paumgarten committed
%option prefix="mcc_parser_"

%option batch
%option bison-bridge
%option bison-locations
%option noinput
%option nounput
%option noyywrap
%option reentrant
%option yylineno

%{
#include "parser.tab.h"

#define YYSTYPE MCC_PARSER_STYPE
#define YYLTYPE MCC_PARSER_LTYPE

/* Update line and column count *
* Reference: https://stackoverflow.com/a/22125500  */

#define YY_USER_ACTION \
yylloc->first_column = yylloc->last_column; \
yylloc->last_column += yyleng; \
for(int i = 0; yytext[i] != '\0'; i++) { \
    if(yytext[i] == '\n') { \
        yylloc->last_line++; \
        yylloc->last_column = 0; \
    } \
    else { \
        yylloc->last_column++; \
    } \
}

int mcc_line_num = 1;
int mcc_comment_caller;
%}

int_literal   [0-9]+
float_literal [0-9]+\.[0-9]+
bool_literal  true|false
string_literal  \"(\\.|[^"\\])*\"

identifier   [a-zA-Z_][a-zA-Z0-9_]*

%x comment foo

/* Scanning comments based on documentation *
 * Documentation: ftp://ftp.gnu.org/old-gnu/Manuals/flex-2.5.4/html_mono/flex.html */

%%


"/*"         {
                mcc_comment_caller = INITIAL;
                BEGIN(comment);
             }

<foo>"/*" {
          mcc_comment_caller = foo;
          BEGIN(comment);
          }

<comment>[^*\n]*        /* eat anything that's not a '*' */
<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */
<comment>\n             ++mcc_line_num;
<comment>"*"+"/"        BEGIN(mcc_comment_caller);

"+"               { return TK_PLUS; }
"-"               { return TK_MINUS; }
"*"               { return TK_ASTER; }
"/"               { return TK_SLASH; }

"("               { return TK_LPARENTH; }
")"               { return TK_RPARENTH; }

"{"               { return TK_LBRACE; }
"}"               { return TK_RBRACE; }

"["               { return TK_LBRACKET; }
"]"               { return TK_RBRACKET; }

"<"               { return TK_LESS; }
">"               { return TK_GREATER; }

"<="              { return TK_LESS_EQ; }
">="              { return TK_GREATER_EQ; }
"=="              { return TK_EQUALS; }
"!="              { return TK_NOT_EQUALS; }

"="               { return TK_ASSIGNMENT; }
";"               { return TK_SEMICOLON; }
","               { return TK_COMMA; }

"!"               { return TK_NOT; }

"&&"              { return TK_AND; }
"||"              { return TK_OR; }

"bool"            { return TK_BOOL_TYPE; }
"int"             { return TK_INT_TYPE; }
"float"           { return TK_FLOAT_TYPE; }
"string"          { return TK_STRING_TYPE; }
"void"            { return TK_VOID; }

"if"              { return TK_IF; }
"else"            { return TK_ELSE; }
"while"           { return TK_WHILE; }
"return"          { return TK_RETURN; }
"for"             { return TK_FOR; }


[ \t\r\n]+        { /* ignore */ }

{bool_literal}    { yylval->TK_BOOL_LITERAL = strcmp(yytext, "true") == 0; return TK_BOOL_LITERAL; }

{identifier}      {
                    yylval->TK_IDENTIFIER = strdup(yytext);
                    return TK_IDENTIFIER;
                  }
{int_literal}     { yylval->TK_INT_LITERAL = atol(yytext); return TK_INT_LITERAL; }

{float_literal}   { yylval->TK_FLOAT_LITERAL = atof(yytext); return TK_FLOAT_LITERAL; }

{string_literal}  { /* https://stackoverflow.com/questions/14185172/lex-how-to-eliminate-double-quotes-from-a-string-literal */
Clemens Paumgarten's avatar
Clemens Paumgarten committed
                    char* str = malloc(sizeof(char) * yyleng+3);
Clemens Paumgarten's avatar
Clemens Paumgarten committed
                    strcpy(str, "\\");
                    strncpy(str+1, yytext, yyleng-1);
                    strcpy(str+yyleng, "\\\"");
                    str[yyleng+2] = '\0';
                    yylval->TK_STRING_LITERAL = str;
                    return TK_STRING_LITERAL;  }
Clemens Paumgarten's avatar
Clemens Paumgarten committed




<<EOF>>           { return TK_END; }



.                 { fprintf(stderr, "invalid character '%c'\n", yytext[0]); }