%{
/**
 * Memory configuration reader
 * Part 1 - lexical analysis 
 * 
 * @file config_lvlib.l
 * @date 2017
 * @author Lukas Vykydal
 *
 * Depends on config_lvlib.tab.h - list of tokens generated from YACC's syntactics description
 */

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

letter [a-zA-Z]
symbol [_\-]
digit  [0-9]
number {digit}+
space  [ \t]*
range  {space}\[{space}{number}{space}:{space}{number}{space}\]

/* 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_R_BRACKET; }
"(" { return TOK_L_BRACKET; }
"}" { return TOK_R_CURLY_BRACKET; }
"{" { return TOK_L_CURLY_BRACKET; }
":" { return TOK_COLLON; }
";" { return TOK_SEMICOLLON; }

"On"|"on"|"ON"    { config_lvlib_yylval.Num = 1; return TOK_NUMBER; }
"Off"|"off"|"OFF" { config_lvlib_yylval.Num = 0; return TOK_NUMBER; }

{number}'b[0-1]+       { config_lvlib_yylval.Num = strtol(yytext, NULL, 2); return TOK_NUMBER;}
{number}'h[0-9A-Fa-f]+ { config_lvlib_yylval.Num = strtol(yytext, NULL, 16); return TOK_NUMBER;}
[-]?{number}           { config_lvlib_yylval.Num = atoi(yytext); return TOK_NUMBER; }
[-]?[0-9.,]+           { config_lvlib_yylval.Double = atof(yytext); return TOK_DOUBLE; }  

({letter}|{digit})({letter}|{digit}|{symbol})*({range})? { config_lvlib_yylval.Text = malloc(strlen(yytext)+1);
                              C_ERROR(config_lvlib_yylval.Text == NULL, "Can't allocate memory");
                              memcpy(config_lvlib_yylval.Text, yytext, strlen(yytext)+1);
                              return TOK_STRING; }

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

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

