%{ /* * 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();} fe { return blifparse::Parser::make_LATCH_FE(); } re { return blifparse::Parser::make_LATCH_RE(); } ah { return blifparse::Parser::make_LATCH_AH(); } al { return blifparse::Parser::make_LATCH_AL(); } as { return blifparse::Parser::make_LATCH_AS(); } NIL { return blifparse::Parser::make_NIL(); } 0 { return blifparse::Parser::make_LOGIC_FALSE(); } 1 { return blifparse::Parser::make_LOGIC_TRUE(); } 2 { return blifparse::Parser::make_LATCH_INIT_2(); } 3 { return blifparse::Parser::make_LATCH_INIT_3(); } {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(); } 0 { return blifparse::Parser::make_LOGIC_FALSE(); } 1 { return blifparse::Parser::make_LOGIC_TRUE(); } \- { return blifparse::Parser::make_LOGIC_DONT_CARE(); } {ENDL} { return blifparse::Parser::make_EOL(); } {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(); } (({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)); } <> { /* 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"); } %%