| %{ |
| /* |
| * 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"); |
| } |
| %% |