OpenSTA/liberty/LibertyLex.ll

210 lines
5.3 KiB
LLVM

%{
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2019, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <ctype.h>
#include <string.h>
#include "Machine.hh"
#include "LibertyParser.hh"
#include "LibertyParse.hh"
#define YY_NO_INPUT
#if defined(YY_FLEX_MAJOR_VERSION) \
&& defined(YY_FLEX_MINOR_VERSION) \
&& YY_FLEX_MAJOR_VERSION >=2 \
&& (YY_FLEX_MINOR_VERSION > 5 \
|| (YY_FLEX_MINOR_VERSION == 5 \
&& defined(YY_FLEX_SUBMINOR_VERSION) \
&& YY_FLEX_SUBMINOR_VERSION >= 31))
#define INCLUDE_SUPPORTED
#endif
static std::string string_buf;
void
libertyParseFlushBuffer()
{
YY_FLUSH_BUFFER;
}
%}
/* %option debug */
%option prefix="LibertyLex_"
%option outfile="lex.yy.c"
%option noyywrap
%option nounput
%option never-interactive
%x comment
%x qstring
DIGIT [0-9]
ALPHA [a-zA-Z]
FLOAT [-+]?(({DIGIT}+\.?{DIGIT}*)|(\.{DIGIT}+))([Ee][-+]?{DIGIT}+)?
BLANK [ \t]
BUS_LEFT [\[<]
BUS_RIGHT [\]>]
BUS_SUB {BUS_LEFT}{DIGIT}+{BUS_RIGHT}
BUS_RANGE {BUS_LEFT}{DIGIT}+:{DIGIT}+{BUS_RIGHT}
PIN_NAME ({ALPHA}|_)({ALPHA}|{DIGIT}|_)*
BUS_NAME {PIN_NAME}({BUS_SUB}|{BUS_RANGE})
MIXED_NAME {BUS_NAME}_{PIN_NAME}
HNAME ({PIN_NAME}|{BUS_NAME}|{MIXED_NAME})([\/.]({PIN_NAME}|{BUS_NAME}|{MIXED_NAME}))+
/* ocv_table_template(2D_ocv_template) */
/* leakage_power_unit : 1pW; */
/* default_operating_conditions : slow_100_3.00 ; */
/* revision : 1.0.17; */
/* default_wire_load : xc2v250-5_avg; */
TOKEN ({ALPHA}|{DIGIT}|_)({ALPHA}|{DIGIT}|[._\-])*
/* bus_naming_style : %s[%d] ; */
BUS_STYLE "%s"{BUS_LEFT}"%d"{BUS_RIGHT}
PUNCTUATION [,\:;|(){}+*&!'=]
TOKEN_END {PUNCTUATION}|[ \t\r\n]
EOL \r?\n
%%
{PUNCTUATION} { return ((int) LibertyLex_text[0]); }
{FLOAT}{TOKEN_END} {
/* Push back the TOKEN_END character. */
yyless(LibertyLex_leng - 1);
LibertyParse_lval.number = static_cast<float>(strtod(LibertyLex_text,
NULL));
return FLOAT;
}
{ALPHA}({ALPHA}|_|{DIGIT})*{TOKEN_END} {
/* Push back the TOKEN_END character. */
yyless(LibertyLex_leng - 1);
LibertyParse_lval.string = sta::stringCopy(LibertyLex_text);
return KEYWORD;
}
{PIN_NAME}{TOKEN_END} |
{BUS_NAME}{TOKEN_END} |
{MIXED_NAME}{TOKEN_END} |
{HNAME}{TOKEN_END} |
{BUS_STYLE}{TOKEN_END} |
{TOKEN}{TOKEN_END} {
/* Push back the TOKEN_END character. */
yyless(LibertyLex_leng - 1);
LibertyParse_lval.string = sta::stringCopy(LibertyLex_text);
return STRING;
}
\\?{EOL} { sta::libertyIncrLine(); }
"include_file"[ \t]*"(".+")"[ \t]*";"? {
#ifdef INCLUDE_SUPPORTED
if (sta::libertyInInclude())
sta::libertyParseError("nested include_file's are not supported\n");
else {
char *filename = &yytext[strlen("include_file")];
/* Skip blanks between include_file and '('. */
while (isspace(*filename) && *filename != '\0')
filename++;
/* Skip '('. */
filename++;
/* Skip blanks between '(' and filename. */
while (isspace(*filename) && *filename != '\0')
filename++;
char *filename_end = strpbrk(filename, ")");
if (filename_end == NULL)
sta::libertyParseError("include_file missing ')'\n");
else {
/* Trim trailing blanks. */
while (isspace(filename_end[-1]) && filename_end > filename)
filename_end--;
*filename_end = '\0';
FILE *stream = sta::libertyIncludeBegin(filename);
if (stream) {
yypush_buffer_state(yy_create_buffer(stream, YY_BUF_SIZE));
BEGIN(INITIAL);
}
}
}
#else
sta::libertyParseError("include_file is not supported.\n");
#endif
}
"/*" BEGIN(comment);
/* Straight out of the flex man page. */
<comment>[^*\r\n]* /* eat anything that's not a '*' */
<comment>"*"+[^*/\r\n]* /* eat up '*'s not followed by '/'s */
<comment>{EOL} sta::libertyIncrLine();
<comment>"*"+"/" BEGIN(INITIAL);
\" {
string_buf.erase();
BEGIN(qstring);
}
<qstring>\" {
BEGIN(INITIAL);
LibertyParse_lval.string = sta::stringCopy(string_buf.c_str());
return STRING;
}
<qstring>{EOL} {
LibertyParse_error("unterminated string constant");
BEGIN(INITIAL);
LibertyParse_lval.string = sta::stringCopy(string_buf.c_str());
return STRING;
}
<qstring>\\{EOL} {
/* Line continuation. */
sta::libertyIncrLine();
}
<qstring>\\. {
/* Escaped character. */
string_buf += '\\';
string_buf += LibertyLex_text[1];
}
<qstring>[^\\\r\n\"]+ {
/* Anything but escape, return or double quote */
string_buf += LibertyLex_text;
}
<qstring><<EOF>> {
LibertyParse_error("unterminated string constant");
BEGIN(INITIAL);
yyterminate();
}
{BLANK}* {}
/* Send out of bound characters to parser. */
. { return (int) LibertyLex_text[0]; }
<<EOF>> {
#ifdef INCLUDE_SUPPORTED
if (sta::libertyInInclude()) {
sta::libertyIncludeEnd();
yypop_buffer_state();
}
else
#endif
yyterminate();
}
%%