OpenFPGA/libs/EXTERNAL/libsdcparse/src/sdc_lexer.l

171 lines
8.0 KiB
Plaintext

%{
/*
* Include Files
*/
#include "sdcparse.hpp"
#include "sdc_common.hpp"
#include "sdc_error.hpp"
#include "sdc_lexer.hpp"
%}
/*
* Options
*/
/* track line numbers*/
%option yylineno
/* No lexing accross files */
%option noyywrap
/* unistd.h doesn't exist on windows */
%option nounistd
/* Avoid unused yyunput function warning */
%option nounput
/* Avoid unused yyinput function warning */
%option noinput
/* isatty() doesn't exist on windows */
%option never-interactive
/* no default rule to echo unrecongaized tokens to output */
%option nodefault
/*%option bison-bridge*/
%option reentrant
/*
* Use a prefix to avoid name clashes with other
* flex lexers
*/
%option prefix="sdcparse_"
/* Common character classes */
BACK_SLASH [\\]
WS [ \t]
ENDL (\n|\n\r|\r\n)
DIGIT10 [0-9]
NAN ((?i:nan)(\([^{WS}]*\))?)
INF (?i:inf|infinity)
FLOAT_BASE (({DIGIT10}*\.?{DIGIT10}+)|({DIGIT10}+\.))
FLOAT_EXP ([eE][-+]?{DIGIT10}+)
FLOAT_NUMBER ({NAN}|([-+]?({INF}|({FLOAT_BASE}{FLOAT_EXP}?))))
INT_NUMBER ([-+]?{DIGIT10}+)
ALPHA [a-zA-Z_]
SYMBOL [-~|:*\\/^]
ID_FIRST ({ALPHA})
ID_MID ({ALPHA}|{DIGIT10}|{SYMBOL})
ID_INDEX (\[{DIGIT10}+\])
ID ({ID_FIRST}{ID_MID}*{ID_INDEX}?)
STR ({ID}|\*{ID}?)
ESCAPED_STR (\{{WS}*[^ \t]*{WS}*\})
/*
* Symbol Definitions
*/
%%
#.* { /* skip comments */ }
{BACK_SLASH}{WS}*{ENDL} { /* line continuation don't send EOL to parser */ }
{ENDL} { return sdcparse::Parser::make_EOL(); }
{WS}+ { /* skip white space */ }
"create_clock" { return sdcparse::Parser::make_CMD_CREATE_CLOCK(); }
"set_input_delay" { return sdcparse::Parser::make_CMD_SET_INPUT_DELAY(); }
"set_output_delay" { return sdcparse::Parser::make_CMD_SET_OUTPUT_DELAY(); }
"set_clock_groups" { return sdcparse::Parser::make_CMD_SET_CLOCK_GROUPS(); }
"set_false_path" { return sdcparse::Parser::make_CMD_SET_FALSE_PATH(); }
"set_max_delay" { return sdcparse::Parser::make_CMD_SET_MAX_DELAY(); }
"set_min_delay" { return sdcparse::Parser::make_CMD_SET_MIN_DELAY(); }
"set_multicycle_path" { return sdcparse::Parser::make_CMD_SET_MULTICYCLE_PATH(); }
"set_clock_uncertainty" { return sdcparse::Parser::make_CMD_SET_CLOCK_UNCERTAINTY(); }
"set_clock_latency" { return sdcparse::Parser::make_CMD_SET_CLOCK_LATENCY(); }
"set_disable_timing" { return sdcparse::Parser::make_CMD_SET_DISABLE_TIMING(); }
"set_timing_derate" { return sdcparse::Parser::make_CMD_SET_TIMING_DERATE(); }
"get_ports" { return sdcparse::Parser::make_CMD_GET_PORTS(); }
"get_clocks" { return sdcparse::Parser::make_CMD_GET_CLOCKS(); }
"get_cells" { return sdcparse::Parser::make_CMD_GET_CELLS(); }
"get_pins" { return sdcparse::Parser::make_CMD_GET_PINS(); }
"-period" { return sdcparse::Parser::make_ARG_PERIOD(); }
"-name" { return sdcparse::Parser::make_ARG_NAME(); }
"-waveform" { return sdcparse::Parser::make_ARG_WAVEFORM(); }
"-clock" { return sdcparse::Parser::make_ARG_CLOCK(); }
"-max" { return sdcparse::Parser::make_ARG_MAX(); }
"-min" { return sdcparse::Parser::make_ARG_MIN(); }
"-exclusive" { return sdcparse::Parser::make_ARG_EXCLUSIVE(); }
"-group" { return sdcparse::Parser::make_ARG_GROUP(); }
"-from" { return sdcparse::Parser::make_ARG_FROM(); }
"-to" { return sdcparse::Parser::make_ARG_TO(); }
"-setup" { return sdcparse::Parser::make_ARG_SETUP(); }
"-hold" { return sdcparse::Parser::make_ARG_HOLD(); }
"-early" { return sdcparse::Parser::make_ARG_EARLY(); }
"-late" { return sdcparse::Parser::make_ARG_LATE(); }
"-cell_delay" { return sdcparse::Parser::make_ARG_CELL_DELAY(); }
"-net_delay" { return sdcparse::Parser::make_ARG_NET_DELAY(); }
"-source" { return sdcparse::Parser::make_ARG_SOURCE(); }
{INT_NUMBER} { return sdcparse::Parser::make_INT_NUMBER(atoi(sdcparse_get_text(yyscanner))); }
{FLOAT_NUMBER} { return sdcparse::Parser::make_FLOAT_NUMBER(atof(sdcparse_get_text(yyscanner))); }
{STR} {
return sdcparse::Parser::make_STRING(sdcparse_get_text(yyscanner));
}
{ESCAPED_STR} {
/*
* Any continguous sequence of non-white space characters,
* with optional leading and/or trailing whitespace that falls
* insde curly braces is interpreted as an escaped string.
* However when we set the yylval, we need to be careful
* to avoid including the curly braces and the leading/trailing
* white-space.
*/
size_t len = strlen(sdcparse_get_text(yyscanner));
char* tmp_str = sdcparse::strndup(sdcparse_get_text(yyscanner)+1, len-2); //Duplicate and trim braces
char* modified_str = tmp_str; //Save the original tmp_str for freeing
//Remove leading whitespace
while(isspace(*modified_str)) modified_str++;
//Find trailing whitespace
char* tmp_ptr = modified_str;
while(!isspace(*tmp_ptr) && *tmp_ptr != '\0') {
tmp_ptr++;
}
//Remove trailing white space
//
//tmp_ptr is now at the first trailing white space character
//(or the existing null terminator), so we can write a '\0'
//to terminate the string here.
*tmp_ptr = '\0';
auto ret = sdcparse::Parser::make_ESCAPED_STRING(modified_str);
//Clean-up the temporary string
free(tmp_str);
return ret;
}
\[ { return sdcparse::Parser::make_LSPAR(); }
\] { return sdcparse::Parser::make_RSPAR(); }
\{ { return sdcparse::Parser::make_LCPAR(); }
\} { return sdcparse::Parser::make_RCPAR(); }
<<EOF>> { /* If the file has no blank line at the end there will
not be the expected EOL following the last command.
So first time through, return EOL, and subsequently
return 0 (which indicated end of file). This ensures
there will always be an EOL provided to the parser.
However it may also generate a stray EOL if the last
line IS blank - so the parse must handle those correctly. */
static bool once; return (once = !once) ? sdcparse::Parser::make_EOL() : sdcparse::Parser::make_EOF();
}
. {
sdc_error_wrap(callback, sdcparse_get_lineno(yyscanner), sdcparse_get_text(yyscanner), "Unrecognized character");
}
%%