%{
/**
 * Microcode - definition parser 
 * Part 1 - lexical analysis 
 * 
 * @file microcode.l
 * @date 2017
 * @author Lukas Vykydal
 *
 * This file describes tokens that can be found in March algorithm file. It uses FLEX (or LEX) to generate 
 * tokenizer based on rules provided below.
 * 
 * Depends on microcode.tab.h - list of tokens generated from YACC's syntactics description
 */

#include "microcode.h"
#include "microcode.tab.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"
%}

letter [a-zA-Z]
digit  [0-9]
number {digit}+

/* To be able to use FLEX generated outut withou -lfl library
   yywrap is used to test if input should wrap to another file after EOF */
%option noyywrap

/* To be able use FLEX without GNU's extensions to C language. This will make program more ANSI C compatible */
%option never-interactive

/* Just to get rid of warnings -Wunused_function*/
%option nounput
%option noinput

/* Exclusive state for multiline comments */
%x c_COMMENT
%%

")" { return TOK_RBRACKET; }
"(" { return TOK_LBRACKET; }
"^" { return TOK_UP; }
"V" { return TOK_DOWN; }
"." { return TOK_SINGLE; }
"_" { return TOK_ROW_ACCESS; }
"|" { return TOK_COL_ACCESS; }
"," { return TOK_COLLON; }

r{number} { microcode_yylval.Num = atoi(yytext + 1); return TOK_READ; }
w{number} { microcode_yylval.Num = atoi(yytext + 1); return TOK_WRITE; }

rc{number} { microcode_yylval.Num = atoi(yytext + 2); return TOK_READ_CHK; }
wc{number} { microcode_yylval.Num = atoi(yytext + 2); return TOK_WRITE_CHK; }

\(w[0,1]r[0,1,x]\)\^n { microcode_yylval.Num = (( yytext[2] - '0' ) & 1) | (( yytext[4] == 'x' ) ? 4 : (( yytext[4] - '0' ) * 2 & 2)); return TOK_SMARCH; }
\(wc[0,1]rc[0,1,x]\)\^n { microcode_yylval.Num = (( yytext[3] - '0' ) & 1) | (( yytext[6] == 'x' ) ? 4 : (( yytext[6] - '0' ) * 2 & 2)); return TOK_SMARCH_CHK; }
NOP        {return TOK_NOP; }


"#define" { return TOK_DEFINE; }

"DELAY" { return TOK_DELAY; }

{letter}({letter}|{digit})+ { microcode_yylval.Text = malloc(strlen(yytext)+1); C_ERROR(microcode_yylval.Text == NULL, "Can't allocate memory"); memcpy(microcode_yylval.Text, yytext, strlen(yytext)+1); return TOK_TEXT; }
{number} { microcode_yylval.Num = atoi(yytext); return TOK_NUMBER; }
[ \t\r] /* skip whitespace */


"/*" { BEGIN(c_COMMENT); }
<c_COMMENT>"*/" { BEGIN(INITIAL); }
<c_COMMENT>\n   { yylineno++; }
<c_COMMENT>.    {}
"//".*\n { yylineno++; }

\n       { yylineno++; }
.        { printf("Unknown character [%c] on line %d", yytext[0], yylineno); exit(1); }

