164 lines
8.1 KiB
Plaintext
164 lines
8.1 KiB
Plaintext
|
%{
|
||
|
/*
|
||
|
* Include Files
|
||
|
*/
|
||
|
#include "blifparse.hpp"
|
||
|
#include "blif_common.hpp"
|
||
|
#include "blif_error.hpp"
|
||
|
|
||
|
#include "blif_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="blifparse_"
|
||
|
|
||
|
/* Common character classes */
|
||
|
ID_SET [^ \t\r\n\\=]
|
||
|
BACK_SLASH [\\]
|
||
|
WS [ \t]
|
||
|
ENDL (\n|\n\r|\r\n)
|
||
|
|
||
|
/* Special Parser States */
|
||
|
%x LATCH
|
||
|
%x NAMES
|
||
|
%x SO_COVER
|
||
|
|
||
|
/*
|
||
|
* Symbol Definitions
|
||
|
*/
|
||
|
%%
|
||
|
<*>#.*{ENDL} { /* ignore comments, but forward EOL for end of line comments */
|
||
|
return blifparse::Parser::make_EOL();
|
||
|
}
|
||
|
^{WS}*{ENDL} { /* Ignore blank lines. */ }
|
||
|
\\{ENDL}{WS}*{ENDL} {
|
||
|
/*
|
||
|
* Do forward end of line if the last line was a continuation.
|
||
|
*
|
||
|
* Some times line continuations are followed by blank lines (which
|
||
|
* are otherwise ignored). In these cases we *do* want to
|
||
|
* forward EOL, so the parser knows the continued line has finished
|
||
|
*/
|
||
|
return blifparse::Parser::make_EOL();
|
||
|
}
|
||
|
<*>\\{ENDL} { /* line continuation (don't forward EOL to parser) */ }
|
||
|
{ENDL} {
|
||
|
return blifparse::Parser::make_EOL();
|
||
|
}
|
||
|
<*>{WS}+ { /* skip white space */ }
|
||
|
<*>\.names {
|
||
|
/*
|
||
|
* To process the single output cover rows of the names directly as symbols
|
||
|
* (rather than as strings) we use a special lexer state.
|
||
|
*/
|
||
|
BEGIN(NAMES);
|
||
|
return blifparse::Parser::make_DOT_NAMES();
|
||
|
}
|
||
|
<*>\.latch {
|
||
|
/*
|
||
|
* The initial state value of a latch is ambiguous (it chould be
|
||
|
* interpreted as a string or logic value string). So we use
|
||
|
* a special lexer state to capture it.
|
||
|
*/
|
||
|
BEGIN(LATCH);
|
||
|
return blifparse::Parser::make_DOT_LATCH();
|
||
|
}
|
||
|
<*>\.model { BEGIN(INITIAL); return blifparse::Parser::make_DOT_MODEL(); }
|
||
|
<*>\.subckt { BEGIN(INITIAL); return blifparse::Parser::make_DOT_SUBCKT(); }
|
||
|
<*>\.inputs { BEGIN(INITIAL); return blifparse::Parser::make_DOT_INPUTS(); }
|
||
|
<*>\.outputs { BEGIN(INITIAL); return blifparse::Parser::make_DOT_OUTPUTS(); }
|
||
|
<*>\.end { BEGIN(INITIAL); return blifparse::Parser::make_DOT_END(); }
|
||
|
<*>\.blackbox { BEGIN(INITIAL); return blifparse::Parser::make_DOT_BLACKBOX(); }
|
||
|
|
||
|
<*>\.conn { BEGIN(INITIAL); return blifparse::Parser::make_DOT_CONN(); /*BLIF extension */}
|
||
|
<*>\.attr { BEGIN(INITIAL); return blifparse::Parser::make_DOT_ATTR(); /*BLIF extension */}
|
||
|
<*>\.param { BEGIN(INITIAL); return blifparse::Parser::make_DOT_PARAM(); /*BLIF extension */}
|
||
|
<*>\.cname { BEGIN(INITIAL); return blifparse::Parser::make_DOT_CNAME(); /*BLIF extension */}
|
||
|
|
||
|
= { return blifparse::Parser::make_EQ();}
|
||
|
<LATCH>fe { return blifparse::Parser::make_LATCH_FE(); }
|
||
|
<LATCH>re { return blifparse::Parser::make_LATCH_RE(); }
|
||
|
<LATCH>ah { return blifparse::Parser::make_LATCH_AH(); }
|
||
|
<LATCH>al { return blifparse::Parser::make_LATCH_AL(); }
|
||
|
<LATCH>as { return blifparse::Parser::make_LATCH_AS(); }
|
||
|
<LATCH>NIL { return blifparse::Parser::make_NIL(); }
|
||
|
<LATCH>0 { return blifparse::Parser::make_LOGIC_FALSE(); }
|
||
|
<LATCH>1 { return blifparse::Parser::make_LOGIC_TRUE(); }
|
||
|
<LATCH>2 { return blifparse::Parser::make_LATCH_INIT_2(); }
|
||
|
<LATCH>3 { return blifparse::Parser::make_LATCH_INIT_3(); }
|
||
|
<LATCH>{ENDL} {
|
||
|
/*
|
||
|
* Latches are only every defined on a single line,
|
||
|
* so when we see the end of a line while in the LATCH
|
||
|
* state we can go back to the regular (INITIAL) state.
|
||
|
*/
|
||
|
BEGIN(INITIAL); return blifparse::Parser::make_EOL();
|
||
|
}
|
||
|
<SO_COVER>0 { return blifparse::Parser::make_LOGIC_FALSE(); }
|
||
|
<SO_COVER>1 { return blifparse::Parser::make_LOGIC_TRUE(); }
|
||
|
<SO_COVER>\- { return blifparse::Parser::make_LOGIC_DONT_CARE(); }
|
||
|
<SO_COVER>{ENDL} { return blifparse::Parser::make_EOL(); }
|
||
|
<NAMES>{ENDL} {
|
||
|
/*
|
||
|
* Once we reach the end of a line in NAMES state (i.e. the end of a .names line)
|
||
|
* we expect the truth table (in single output cover format) to follow, so we enter
|
||
|
* the SO_COVER state.
|
||
|
*/
|
||
|
BEGIN(SO_COVER);
|
||
|
return blifparse::Parser::make_EOL();
|
||
|
}
|
||
|
<INITIAL,NAMES,LATCH>(({ID_SET}|{BACK_SLASH})*{ID_SET}) {
|
||
|
/*
|
||
|
* We allow all sorts of characters in regular strings.
|
||
|
* However we need to be careful about line continuations
|
||
|
* in particular, it is possible that we could have a string
|
||
|
* followed by a continuation with no space for this reason,
|
||
|
* we do not allow a continuation (backslash, \\ in escaped
|
||
|
* form in the regex) in the last character of the string.
|
||
|
*/
|
||
|
return blifparse::Parser::make_STRING(blifparse_get_text(yyscanner));
|
||
|
}
|
||
|
<<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 parser must handle those correclty. */
|
||
|
static bool once; return (once = !once) ? blifparse::Parser::make_EOL() : blifparse::Parser::make_EOF();
|
||
|
}
|
||
|
<*>. { blifparse::blif_error_wrap(callback, blifparse_get_lineno(yyscanner), blifparse_get_text(yyscanner), "Unrecognized character"); }
|
||
|
%%
|