181 lines
4.5 KiB
LLVM
181 lines
4.5 KiB
LLVM
%{
|
|
// OpenSTA, Static Timing Analyzer
|
|
// Copyright (c) 2025, 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/>.
|
|
//
|
|
// The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software.
|
|
//
|
|
// Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
//
|
|
// This notice may not be removed or altered from any source distribution.
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#include "util/FlexDisableRegister.hh"
|
|
#include "liberty/LibertyParser.hh"
|
|
#include "LibertyParse.hh"
|
|
#include "liberty/LibertyScanner.hh"
|
|
|
|
#undef YY_DECL
|
|
#define YY_DECL \
|
|
int \
|
|
sta::LibertyScanner::lex(sta::LibertyParse::semantic_type *const yylval, \
|
|
sta::LibertyParse::location_type *loc)
|
|
|
|
// update location on matching
|
|
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
|
|
|
|
typedef sta::LibertyParse::token token;
|
|
|
|
%}
|
|
|
|
%option c++
|
|
%option yyclass="sta::LibertyScanner"
|
|
%option prefix="Liberty"
|
|
%option noyywrap
|
|
%option never-interactive
|
|
%option stack
|
|
%option yylineno
|
|
/* %option debug */
|
|
|
|
%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})
|
|
BUS_NAME2 {PIN_NAME}{BUS_SUB}({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}|[._\-])*(:({ALPHA}|{DIGIT}|_)+)?
|
|
/* bus_naming_style : %s[%d] ; */
|
|
BUS_STYLE "%s"{BUS_LEFT}"%d"{BUS_RIGHT}
|
|
PUNCTUATION [,\:;|(){}+*&!'=]
|
|
TOKEN_END {PUNCTUATION}|[ \t\r\n]|\\{EOL}
|
|
EOL \r?\n
|
|
%%
|
|
|
|
{PUNCTUATION} { return ((int) yytext[0]); }
|
|
|
|
{FLOAT}{TOKEN_END} {
|
|
/* Push back the TOKEN_END character. */
|
|
yyless(yyleng - 1);
|
|
yylval->number = strtod(yytext, nullptr);
|
|
return token::FLOAT;
|
|
}
|
|
|
|
{ALPHA}({ALPHA}|_|{DIGIT})*{TOKEN_END} {
|
|
/* Push back the TOKEN_END character. */
|
|
yyless(yyleng - 1);
|
|
yylval->string = sta::stringCopy(yytext);
|
|
return token::KEYWORD;
|
|
}
|
|
|
|
{PIN_NAME}{TOKEN_END} |
|
|
{BUS_NAME}{TOKEN_END} |
|
|
{BUS_NAME2}{TOKEN_END} |
|
|
{MIXED_NAME}{TOKEN_END} |
|
|
{HNAME}{TOKEN_END} |
|
|
{BUS_STYLE}{TOKEN_END} |
|
|
{TOKEN}{TOKEN_END} {
|
|
/* Push back the TOKEN_END character. */
|
|
yyless(yyleng - 1);
|
|
yylval->string = sta::stringCopy(yytext);
|
|
return token::STRING;
|
|
}
|
|
|
|
\\?{EOL} { loc->lines(); loc->step(); }
|
|
|
|
"include_file"[ \t]*"(".+")"[ \t]*";"? {
|
|
if (includeBegin()) {
|
|
BEGIN(INITIAL);
|
|
}
|
|
}
|
|
|
|
"/*" 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} { loc->lines(); loc->step(); }
|
|
<comment>"*"+"/" BEGIN(INITIAL);
|
|
|
|
\" {
|
|
token_.clear();
|
|
BEGIN(qstring);
|
|
}
|
|
|
|
<qstring>\" {
|
|
BEGIN(INITIAL);
|
|
yylval->string = stringCopy(token_.c_str());
|
|
return token::STRING;
|
|
}
|
|
|
|
<qstring>{EOL} {
|
|
error("unterminated string constant");
|
|
BEGIN(INITIAL);
|
|
yylval->string = stringCopy(token_.c_str());
|
|
return token::STRING;
|
|
}
|
|
|
|
<qstring>\\{EOL} {
|
|
/* Line continuation. */
|
|
loc->lines(); loc->step();
|
|
}
|
|
|
|
<qstring>\\. {
|
|
/* Escaped character. */
|
|
token_ += '\\';
|
|
token_ += yytext[1];
|
|
}
|
|
|
|
<qstring>[^\\\r\n\"]+ {
|
|
/* Anything but escape, return or double quote */
|
|
token_ += yytext;
|
|
}
|
|
|
|
<qstring><<EOF>> {
|
|
error("unterminated string constant");
|
|
BEGIN(INITIAL);
|
|
yyterminate();
|
|
}
|
|
|
|
{BLANK}* {}
|
|
/* Send out of bound characters to parser. */
|
|
. { return (int) yytext[0]; }
|
|
|
|
<<EOF>> { if (stream_prev_)
|
|
fileEnd();
|
|
else
|
|
yyterminate();
|
|
}
|
|
|
|
%%
|