Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
3.9 kB
2
Indexable
Never
/*
 *  The scanner definition for COOL.
 */

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

/* Definitions */
#define MAX_STR_CONST 1025

extern FILE *fin;
extern int curr_lineno;
extern YYSTYPE cool_yylval;

/* Function Declarations */
int handle_error(const char *msg);
bool read_char(char ch);
%}

/* Tokens */
%{
#define CLASS 1
#define IF 2
#define THEN 3
#define ELSE 4
#define FI 5
#define IN 6
#define INHERITS 7
#define ISVOID 8
#define LET 9
#define LOOP 10
#define POOL 11
#define WHILE 12
#define CASE 13
#define ESAC 14
#define NEW 15
#define OF 16
#define NOT 17
#define DARROW 18
#define LE 19
#define ASSIGN 20
#define BOOL_CONST 21
#define INT_CONST 22
#define TYPEID 23
#define OBJECTID 24
#define STR_CONST 25
#define ERROR 26
%}

/* Regular Expressions */
%{
DIGIT       [0-9]
ALPHANUM    [0-9a-zA-Z_]
WHITESPACE  [ \t\r\f\v]

QUOTES      \"
SINGLE_TOKENS [{|}|(|)|:|;|@|,|.|+|\-|*|/|=|<|~]
%}

%%
{WHITESPACE}+    ; /* skip whitespace */
\n               { curr_lineno++; }

{SINGLE_TOKENS}  { return yytext[0]; }

"true"           { cool_yylval.boolean = 1; return BOOL_CONST; }
"false"          { cool_yylval.boolean = 0; return BOOL_CONST; }

{CLASS}          { return CLASS; }
{IF}             { return IF; }
{THEN}           { return THEN; }
{ELSE}           { return ELSE; }
{FI}             { return FI; }
{IN}             { return IN; }
{INHERITS}       { return INHERITS; }
{ISVOID}         { return ISVOID; }
{LET}            { return LET; }
{LOOP}           { return LOOP; }
{POOL}           { return POOL; }
{WHILE}          { return WHILE; }
{CASE}           { return CASE; }
{ESAC}           { return ESAC; }
{NEW}            { return NEW; }
{OF}             { return OF; }
{NOT}            { return NOT; }

"=>"             { return DARROW; }
"<-"             { return ASSIGN; }
"<="             { return LE; }

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

[A-Z]{ALPHANUM}* { cool_yylval.symbol = idtable.add_string(yytext); return TYPEID; }
[a-z]{ALPHANUM}* { cool_yylval.symbol = idtable.add_string(yytext); return OBJECTID; }

\"               { yytext[0] = '\0'; string_buf_ptr = string_buf; BEGIN(STR); }

"--".*           ; /* single-line comment */

"(*"             { /* multi-line comment */
                    commentLevel++;
                    BEGIN COMMENT;
                  }

.                { return handle_error(yytext); }

%%

int handle_error(const char *msg) {
    cool_yylval.error_msg = msg;
    return ERROR;
}

/* Multi-line Comment */
<COMMENT>{
    [^(*\n]*    ; /* skip characters */
    \n          { curr_lineno++; }
    (*          { commentLevel++; }
    *+          { /* handle *+ */ }
    *)          { commentLevel--; if (commentLevel == 0) BEGIN(INITIAL); }
    <<EOF>>     { return handle_error("EOF in comment"); }
}

/* String */
<STR>{
    {QUOTES} {
        *string_buf_ptr = '\0';
        cool_yylval.symbol = stringtable.add_string(string_buf);
        BEGIN(INITIAL);
        return STR_CONST;
    }

    <<EOF>> {
        return handle_error("EOF in string constant");
    }

    (\0|\\\0) {
        return handle_error("Null character in string");
    }

    \n {
        curr_lineno++;
        return handle_error("Unterminated string constant");
    }

    \\[ntrbf] {
        char ch;
        switch (yytext[1]) {
            case 'n': ch = '\n'; break;
            case 't': ch = '\t'; break;
            case 'r': ch = '\r'; break;
            case 'b': ch = '\b'; break;
            case 'f': ch = '\f'; break;
        }
        if (!read_char(ch)) return handle_error("String constant too long");
    }

    [^\\\n\"]+ {
        if (!read_char(yytext[0])) return handle_error("String constant too long");
    }
}

bool read_char(char ch) {
    if (string_buf_ptr - string_buf >= MAX_STR_CONST) return false;
    *string_buf_ptr++ = ch;
    return true;
}
Leave a Comment