2006-08-26 11:35:28 +00:00
|
|
|
|
/**************************************************************************
|
|
|
|
|
* DESCRIPTION: Verilator: Flex verilog preprocessor
|
|
|
|
|
*
|
2008-04-25 12:14:27 +00:00
|
|
|
|
* Code available from: http://www.veripool.org/verilator
|
2006-08-26 11:35:28 +00:00
|
|
|
|
*
|
|
|
|
|
**************************************************************************
|
|
|
|
|
*
|
2010-02-07 11:40:48 +00:00
|
|
|
|
* Copyright 2003-2010 by Wilson Snyder. This program is free software;
|
|
|
|
|
* you can redistribute it and/or modify it under the terms of either the
|
|
|
|
|
* GNU Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
* Version 2.0.
|
2006-08-26 11:35:28 +00:00
|
|
|
|
*
|
|
|
|
|
* Verilator 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.
|
|
|
|
|
*
|
|
|
|
|
**************************************************************************
|
|
|
|
|
* Do not use Flex in C++ mode. It has bugs with yyunput() which result in
|
|
|
|
|
* lost characters.
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
%option noyywrap align interactive
|
|
|
|
|
%option stack
|
|
|
|
|
%option noc++
|
|
|
|
|
%option prefix="V3PreLex"
|
|
|
|
|
%{
|
|
|
|
|
|
|
|
|
|
#include "V3PreProc.h"
|
|
|
|
|
#include "V3PreLex.h"
|
|
|
|
|
|
|
|
|
|
V3PreLex* V3PreLex::s_currentLexp = NULL; // Current lexing point
|
|
|
|
|
|
2009-12-21 13:54:39 +00:00
|
|
|
|
#define LEXP V3PreLex::s_currentLexp
|
|
|
|
|
|
2010-04-07 00:20:44 +00:00
|
|
|
|
#define YY_INPUT(buf,result,max_size) \
|
|
|
|
|
result = LEXP->inputToLex(buf,max_size);
|
|
|
|
|
|
2010-03-05 17:02:56 +00:00
|
|
|
|
// Accessors, because flex keeps changing the type of yyleng
|
|
|
|
|
char* yyourtext() { return yytext; }
|
|
|
|
|
size_t yyourleng() { return yyleng; }
|
|
|
|
|
void yyourtext(const char* textp, size_t size) { yytext=(char*)textp; yyleng=size; }
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Prevent conflicts from perl version
|
2009-12-21 13:54:39 +00:00
|
|
|
|
static void linenoInc() {LEXP->incLineno();}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
static bool optPsl() { return V3PreProc::optPsl(); }
|
2009-12-21 13:54:39 +00:00
|
|
|
|
static bool pedantic() { return LEXP->m_pedantic; }
|
|
|
|
|
static void yyerror(char* msg) { LEXP->m_curFilelinep->v3error(msg); }
|
|
|
|
|
static void yyerrorf(const char* msg) { LEXP->m_curFilelinep->v3error(msg); }
|
2010-04-07 00:20:44 +00:00
|
|
|
|
static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t,l); }
|
2009-12-21 13:54:39 +00:00
|
|
|
|
static int pslParenLevel() { return LEXP->m_pslParenLevel; }
|
|
|
|
|
static void pslParenLevelInc() { LEXP->m_pslParenLevel++; }
|
|
|
|
|
static void pslParenLevelDec() { if (pslParenLevel()) LEXP->m_pslParenLevel--; }
|
|
|
|
|
static bool pslMoreNeeded() { return LEXP->m_pslMoreNeeded; }
|
|
|
|
|
static void pslMoreNeeded(bool flag) { LEXP->m_pslMoreNeeded = flag; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
/**********************************************************************/
|
|
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
%x PSLONEM
|
|
|
|
|
%x PSLONEE
|
|
|
|
|
%x PSLMULM
|
|
|
|
|
%x PSLMUL1
|
|
|
|
|
%x CMTONEM
|
|
|
|
|
%x CMTBEGM
|
|
|
|
|
%x CMTMODE
|
|
|
|
|
%x STRMODE
|
2009-05-11 15:57:43 +00:00
|
|
|
|
%x DEFFPAR
|
|
|
|
|
%x DEFFORM
|
|
|
|
|
%x DEFVAL
|
2010-01-28 14:41:24 +00:00
|
|
|
|
%x DEFCMT
|
2006-08-26 11:35:28 +00:00
|
|
|
|
%x ARGMODE
|
|
|
|
|
%x INCMODE
|
2007-05-18 14:03:50 +00:00
|
|
|
|
%x PRTMODE
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2007-05-17 16:15:24 +00:00
|
|
|
|
/* drop: Drop Ctrl-Z - can't pass thru or may EOF the output too soon */
|
|
|
|
|
|
2006-09-13 14:38:48 +00:00
|
|
|
|
ws [ \t\f\r]
|
|
|
|
|
wsn [ \t\f]
|
|
|
|
|
crnl [\r]*[\n]
|
2006-08-26 11:35:28 +00:00
|
|
|
|
quote [\"]
|
|
|
|
|
backslash [\\]
|
2009-07-31 16:02:43 +00:00
|
|
|
|
symb ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n]+)
|
2010-04-07 00:20:44 +00:00
|
|
|
|
word [a-zA-Z0-9_]+
|
2007-05-17 16:15:24 +00:00
|
|
|
|
drop [\032]
|
2006-08-26 11:35:28 +00:00
|
|
|
|
psl [p]sl
|
|
|
|
|
|
|
|
|
|
/**************************************************************/
|
|
|
|
|
%%
|
|
|
|
|
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { LEXP->lineDirective(yytext);
|
2007-06-13 17:34:09 +00:00
|
|
|
|
return(VP_LINE); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2007-12-13 13:54:04 +00:00
|
|
|
|
/* Special directives we recognize */
|
2009-12-21 03:26:48 +00:00
|
|
|
|
<INITIAL>"`define" { return(VP_DEFINE); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<INITIAL>"`else" { return(VP_ELSE); }
|
|
|
|
|
<INITIAL>"`elsif" { return(VP_ELSIF); }
|
|
|
|
|
<INITIAL>"`endif" { return(VP_ENDIF); }
|
2009-12-21 03:26:48 +00:00
|
|
|
|
<INITIAL>"`ifdef" { return(VP_IFDEF); }
|
|
|
|
|
<INITIAL>"`ifndef" { return(VP_IFNDEF); }
|
|
|
|
|
<INITIAL>"`include" { return(VP_INCLUDE); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<INITIAL>"`undef" { return(VP_UNDEF); }
|
2009-12-21 03:26:48 +00:00
|
|
|
|
<INITIAL>"`undefineall" { return(VP_UNDEFINEALL); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2007-12-13 13:54:04 +00:00
|
|
|
|
/* Optional directives we recognize */
|
2009-12-24 16:40:56 +00:00
|
|
|
|
<INITIAL>"`__FILE__" { static string rtnfile;
|
2010-01-19 23:59:45 +00:00
|
|
|
|
rtnfile = '"'; rtnfile += LEXP->m_curFilelinep->filename().c_str();
|
2009-12-24 16:40:56 +00:00
|
|
|
|
rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length();
|
|
|
|
|
return (VP_STRING); }
|
|
|
|
|
<INITIAL>"`__LINE__" { static char buf[10];
|
|
|
|
|
sprintf(buf, "%d",LEXP->m_curFilelinep->lineno());
|
|
|
|
|
yytext = buf; yyleng = strlen(yytext);
|
|
|
|
|
return (VP_TEXT); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<INITIAL>"`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); }
|
|
|
|
|
|
|
|
|
|
/* Pass-through strings */
|
|
|
|
|
<INITIAL,PSLMULM,PSLONEM>{quote} { yy_push_state(STRMODE); yymore(); }
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<STRMODE><<EOF>> { linenoInc(); yyerrorf("EOF in unterminated string"); yyleng=0; yyterminate(); }
|
|
|
|
|
<STRMODE>{crnl} { linenoInc(); yyerrorf("Unterminated string"); BEGIN(INITIAL); }
|
2010-04-07 00:20:44 +00:00
|
|
|
|
<STRMODE>{word} { yymore(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<STRMODE>[^\"\\] { yymore(); }
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<STRMODE>{backslash}{crnl} { linenoInc(); yymore(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<STRMODE>{backslash}. { yymore(); }
|
|
|
|
|
<STRMODE>{quote} { yy_pop_state();
|
2009-12-21 13:54:39 +00:00
|
|
|
|
if (LEXP->m_parenLevel || LEXP->m_formalLevel) { appendDefValue(yytext,yyleng); yyleng=0; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
else return (VP_STRING); }
|
|
|
|
|
|
2007-05-18 14:03:50 +00:00
|
|
|
|
/* Protected blocks */
|
|
|
|
|
<INITIAL>"`protected" { yy_push_state(PRTMODE); yymore(); }
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<PRTMODE><<EOF>> { linenoInc(); yyerrorf("EOF in `protected"); yyleng=0; yyterminate(); }
|
2007-05-18 14:03:50 +00:00
|
|
|
|
<PRTMODE>{crnl} { linenoInc(); yymore(); }
|
|
|
|
|
<PRTMODE>. { yymore(); }
|
|
|
|
|
<PRTMODE>"`endprotected" { yy_pop_state(); return (VP_TEXT); }
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
/* Pass-through include <> filenames */
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<INCMODE><<EOF>> { linenoInc(); yyerrorf("EOF in unterminated include filename"); yyleng=0; yyterminate(); }
|
|
|
|
|
<INCMODE>{crnl} { linenoInc(); yyerrorf("Unterminated include filename"); BEGIN(INITIAL); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<INCMODE>[^\>\\] { yymore(); }
|
|
|
|
|
<INCMODE>{backslash}. { yymore(); }
|
|
|
|
|
<INCMODE>[\>] { yy_pop_state(); return (VP_STRING); }
|
|
|
|
|
|
2009-05-11 15:57:43 +00:00
|
|
|
|
/* Reading definition formal parenthesis (or not) to begin formal arguments */
|
|
|
|
|
/* Note '(' must IMMEDIATELY follow definition name */
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<DEFFPAR>[(] { appendDefValue("(",1); LEXP->m_formalLevel=1; BEGIN(DEFFORM); }
|
2009-05-11 15:57:43 +00:00
|
|
|
|
<DEFFPAR>{crnl} { yy_pop_state(); unput('\n'); yyleng=0; return VP_DEFFORM; } /* DEFVAL will later grab the return */
|
2009-09-18 02:23:18 +00:00
|
|
|
|
<DEFFPAR><<EOF>> { yy_pop_state(); return VP_DEFFORM; } /* empty formals */
|
2009-05-11 15:57:43 +00:00
|
|
|
|
<DEFFPAR>. { yy_pop_state(); unput(yytext[yyleng-1]); yyleng=0; return VP_DEFFORM; } /* empty formals */
|
2009-12-21 13:54:39 +00:00
|
|
|
|
|
2009-05-11 15:57:43 +00:00
|
|
|
|
/* Reading definition formals */
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<DEFFORM>[(] { appendDefValue(yytext,yyleng); yyleng=0; ++LEXP->m_formalLevel; }
|
|
|
|
|
<DEFFORM>[)] { appendDefValue(yytext,yyleng); yyleng=0; if ((--LEXP->m_formalLevel)==0) { yy_pop_state(); return VP_DEFFORM; } }
|
2009-05-11 15:57:43 +00:00
|
|
|
|
<DEFFORM>"/*" { yy_push_state(CMTMODE); yymore(); }
|
|
|
|
|
<DEFFORM>"//"[^\n\r]* { return (VP_COMMENT);}
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<DEFFORM>{drop} { }
|
2009-05-11 15:57:43 +00:00
|
|
|
|
<DEFFORM><<EOF>> { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; }
|
|
|
|
|
<DEFFORM>{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */
|
|
|
|
|
<DEFFORM>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<DEFFORM>{quote} { yy_push_state(STRMODE); yymore(); }
|
|
|
|
|
<DEFFORM>[{\[] { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); }
|
|
|
|
|
<DEFFORM>[}\]] { LEXP->m_formalLevel--; appendDefValue(yytext,yyleng); }
|
|
|
|
|
<DEFFORM>[^\/\*\n\r\\(){}\[\]\"]+ |
|
2009-05-11 15:57:43 +00:00
|
|
|
|
<DEFFORM>[\\][^\n\r] |
|
|
|
|
|
<DEFFORM>. { appendDefValue(yytext,yyleng); }
|
|
|
|
|
|
|
|
|
|
/* Reading definition value */
|
2010-01-28 14:41:24 +00:00
|
|
|
|
<DEFVAL>"/*" { LEXP->m_defCmtSlash=false; yy_push_state(DEFCMT); yymore(); } /* Special comment parser */
|
2010-02-19 01:57:46 +00:00
|
|
|
|
<DEFVAL>"//"[^\n\r]*[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Spec says // not part of define value */
|
2009-05-11 15:57:43 +00:00
|
|
|
|
<DEFVAL>"//"[^\n\r]* { return (VP_COMMENT);}
|
|
|
|
|
<DEFVAL>{drop} { }
|
|
|
|
|
<DEFVAL><<EOF>> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */
|
|
|
|
|
<DEFVAL>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); }
|
2010-01-28 14:41:24 +00:00
|
|
|
|
<DEFVAL>[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Return, but not \ is part of define value */
|
2009-05-11 15:57:43 +00:00
|
|
|
|
<DEFVAL>[^\/\*\n\r\\]+ |
|
|
|
|
|
<DEFVAL>[\\][^\n\r] |
|
2010-04-07 00:20:44 +00:00
|
|
|
|
<DEFVAL>{word} { appendDefValue(yytext,yyleng); }
|
2009-05-11 15:57:43 +00:00
|
|
|
|
<DEFVAL>. { appendDefValue(yytext,yyleng); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2010-01-28 14:41:24 +00:00
|
|
|
|
/* Comments inside define values - if embedded get added to define value per spec */
|
|
|
|
|
/* - if no \{crnl} ending then the comment belongs to the next line, as a non-embedded comment */
|
|
|
|
|
/* - if all but (say) 3rd line is missing \ then it's indeterminate */
|
|
|
|
|
<DEFCMT>"*/" { yy_pop_state(); appendDefValue(yytext,yyleng); }
|
|
|
|
|
<DEFCMT>[\\]{crnl} { linenoInc(); LEXP->m_defCmtSlash=true;
|
|
|
|
|
appendDefValue(yytext,yyleng-2); appendDefValue((char*)"\n",1); } /* Return but not \ */
|
|
|
|
|
<DEFCMT>{crnl} { linenoInc(); yymore(); if (LEXP->m_defCmtSlash) yyerrorf("One line of /* ... */ is missing \\ before newline");
|
|
|
|
|
BEGIN(CMTMODE); }
|
2010-04-07 00:20:44 +00:00
|
|
|
|
<DEFCMT>{word} { yymore(); }
|
2010-01-28 14:41:24 +00:00
|
|
|
|
<DEFCMT>. { yymore(); }
|
|
|
|
|
<DEFCMT><<EOF>> { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); }
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
/* Define arguments */
|
|
|
|
|
<ARGMODE>"/*" { yy_push_state(CMTMODE); yymore(); }
|
2006-09-13 14:38:48 +00:00
|
|
|
|
<ARGMODE>"//"[^\n\r]* { return (VP_COMMENT);}
|
2007-05-17 16:15:24 +00:00
|
|
|
|
<ARGMODE>{drop} { }
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<ARGMODE><<EOF>> { yyerrorf("EOF in define argument list\n"); yyleng = 0; yyterminate(); }
|
|
|
|
|
<ARGMODE>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<ARGMODE>{quote} { yy_push_state(STRMODE); yymore(); }
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<ARGMODE>[{\[] { LEXP->m_parenLevel++; appendDefValue(yytext,yyleng); }
|
|
|
|
|
<ARGMODE>[}\]] { LEXP->m_parenLevel--; appendDefValue(yytext,yyleng); }
|
|
|
|
|
<ARGMODE>[(] { LEXP->m_parenLevel++;
|
2008-04-25 14:01:50 +00:00
|
|
|
|
// Note paren level 0 means before "(" of starting args
|
|
|
|
|
// Level 1 means "," between arguments
|
2008-06-10 01:25:10 +00:00
|
|
|
|
// Level 2+ means one argument's internal ()
|
2009-12-21 13:54:39 +00:00
|
|
|
|
if (LEXP->m_parenLevel>1) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
appendDefValue(yytext,yyleng);
|
|
|
|
|
} else {
|
2008-03-27 13:21:49 +00:00
|
|
|
|
return (VP_TEXT);
|
2008-06-12 16:03:47 +00:00
|
|
|
|
}}
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<ARGMODE>[)] { LEXP->m_parenLevel--;
|
|
|
|
|
if (LEXP->m_parenLevel>0) {
|
2008-03-27 13:21:49 +00:00
|
|
|
|
appendDefValue(yytext,yyleng);
|
|
|
|
|
} else {
|
|
|
|
|
yy_pop_state(); return (VP_DEFARG);
|
2008-06-12 16:03:47 +00:00
|
|
|
|
}}
|
2009-12-21 13:54:39 +00:00
|
|
|
|
<ARGMODE>[,] { if (LEXP->m_parenLevel>1) {
|
2008-03-27 13:21:49 +00:00
|
|
|
|
appendDefValue(yytext,yyleng);
|
|
|
|
|
} else {
|
|
|
|
|
yy_pop_state(); return (VP_DEFARG);
|
2008-06-12 16:03:47 +00:00
|
|
|
|
}}
|
2008-03-27 13:21:49 +00:00
|
|
|
|
<ARGMODE>"`"{symb} { return (VP_DEFREF); } /* defref in defref */
|
2008-06-04 15:39:44 +00:00
|
|
|
|
<ARGMODE>[^\/\*\n\r\\(,){}\[\]\"`]+ |
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<ARGMODE>. { appendDefValue(yytext,yyleng); }
|
|
|
|
|
|
|
|
|
|
/* One line comments. */
|
|
|
|
|
<INITIAL>"//"{ws}*{psl} { if (optPsl()) { pslMoreNeeded(true); yy_push_state(PSLONEM); return(VP_PSL); }
|
|
|
|
|
else { yy_push_state(CMTONEM); yymore(); } }
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<INITIAL>"//"{ws}*{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return (VP_WHITE); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<INITIAL>"//" { if (pslMoreNeeded()) { pslMoreNeeded(true); yy_push_state(PSLONEM); return(VP_PSL); }
|
|
|
|
|
else { yy_push_state(CMTONEM); yymore(); } }
|
2006-09-13 14:38:48 +00:00
|
|
|
|
<CMTONEM>[^\n\r]* { yy_pop_state(); return (VP_COMMENT); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
/* Psl oneline comments */
|
|
|
|
|
<PSLONEM>[{(] { pslParenLevelInc(); return (VP_TEXT); }
|
|
|
|
|
<PSLONEM>[})] { pslParenLevelDec(); return (VP_TEXT); }
|
|
|
|
|
<PSLONEM>[;] { if (!pslParenLevel()) {BEGIN PSLONEE; pslMoreNeeded(false);} return (VP_TEXT); }
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<PSLONEM>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
/* Completed psl oneline comments */
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<PSLONEE>{crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<PSLONEE>{ws}+ { yymore(); }
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<PSLONEE>. { yyerrorf("Unexpected text following psl assertion\n"); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
/* C-style comments. */
|
2010-01-28 14:41:24 +00:00
|
|
|
|
/**** See also DEFCMT */
|
2006-08-26 11:35:28 +00:00
|
|
|
|
/* We distinguish between the start of a comment, and later, so we may find a "psl" prefix */
|
|
|
|
|
<INITIAL>"/*" { yy_push_state(optPsl() ? CMTBEGM : CMTMODE); yymore(); }
|
|
|
|
|
<CMTBEGM>{psl} { yyleng -= 3; BEGIN PSLMUL1; return (VP_COMMENT); }
|
|
|
|
|
<CMTBEGM>{ws}+ { yymore(); }
|
|
|
|
|
<CMTBEGM,CMTMODE>"*/" { yy_pop_state(); return(VP_COMMENT); }
|
2006-09-13 14:38:48 +00:00
|
|
|
|
<CMTBEGM,CMTMODE>{crnl} { linenoInc(); yymore(); }
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<CMTBEGM,CMTMODE><<EOF>> { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); }
|
2010-04-07 00:20:44 +00:00
|
|
|
|
<CMTMODE>{word} { yymore(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<CMTBEGM>. { BEGIN CMTMODE; yymore(); } /* Non 'psl' beginning in comment */
|
|
|
|
|
<CMTMODE>. { yymore(); }
|
|
|
|
|
|
|
|
|
|
/* Psl C-style comments. */
|
2009-09-18 02:23:18 +00:00
|
|
|
|
/* EOFs are normal because / * `foo(..) * / hits a unputString EOF */
|
2006-09-13 14:38:48 +00:00
|
|
|
|
<PSLMUL1>.|{crnl} { yyless(0); BEGIN PSLMULM; return(VP_PSL); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<PSLMULM>"*/" { yy_pop_state(); return(VP_COMMENT); }
|
2006-09-13 14:38:48 +00:00
|
|
|
|
<PSLMULM>"//"[^\n\r]* { return (VP_COMMENT); } /* Comments inside block comments get literal inclusion (later removal) */
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
/* Define calls */
|
|
|
|
|
<INITIAL,PSLMULM,PSLONEM>"`"{symb} { return (VP_DEFREF); }
|
|
|
|
|
|
|
|
|
|
/* Generics */
|
2008-04-29 14:14:20 +00:00
|
|
|
|
<INITIAL,PSLMULM>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
|
2009-09-18 02:23:18 +00:00
|
|
|
|
<INITIAL,PSLMULM,PSLONEM><<EOF>> { yyterminate(); } /* A "normal" EOF */
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<INITIAL,PSLMULM,PSLONEM>{symb} { return (VP_SYMBOL); }
|
2006-09-13 14:38:48 +00:00
|
|
|
|
<INITIAL,PSLMULM,PSLONEM>{wsn}+ { return (VP_WHITE); }
|
2007-05-17 16:15:24 +00:00
|
|
|
|
<INITIAL,PSLMULM,PSLONEM>{drop} { }
|
|
|
|
|
<INITIAL,PSLMULM,PSLONEM>[\r] { }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
<INITIAL,PSLMULM,PSLONEM>. { return (VP_TEXT); }
|
|
|
|
|
%%
|
|
|
|
|
|
2008-04-25 14:01:50 +00:00
|
|
|
|
void V3PreLex::pushStateDefArg(int level) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Enter define substitution argument state
|
|
|
|
|
yy_push_state(ARGMODE);
|
2008-04-25 14:01:50 +00:00
|
|
|
|
m_parenLevel = level;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
m_defValue = "";
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-11 15:57:43 +00:00
|
|
|
|
void V3PreLex::pushStateDefForm() {
|
|
|
|
|
// Enter define formal arguments state
|
|
|
|
|
yy_push_state(DEFFPAR); // First is an optional ( to begin args
|
|
|
|
|
m_parenLevel = 0;
|
|
|
|
|
m_defValue = "";
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-27 13:21:49 +00:00
|
|
|
|
void V3PreLex::pushStateDefValue() {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Enter define value state
|
2009-05-11 15:57:43 +00:00
|
|
|
|
yy_push_state(DEFVAL);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
m_parenLevel = 0;
|
|
|
|
|
m_defValue = "";
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-27 13:21:49 +00:00
|
|
|
|
void V3PreLex::pushStateIncFilename() {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Enter include <> filename state
|
|
|
|
|
yy_push_state(INCMODE);
|
|
|
|
|
yymore();
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-07 00:20:44 +00:00
|
|
|
|
void V3PreLex::initFirstBuffer() {
|
|
|
|
|
// Called from constructor to make first buffer
|
|
|
|
|
// yy_create_buffer also sets yy_fill_buffer=1 so reads from YY_INPUT
|
|
|
|
|
yy_switch_to_buffer(yy_create_buffer(NULL, YY_BUF_SIZE));
|
|
|
|
|
m_bufferStack.push(currentBuffer());
|
|
|
|
|
yyrestart(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t V3PreLex::inputToLex(char* buf, size_t max_size) {
|
|
|
|
|
// We need a custom YY_INPUT because we can't use flex buffers.
|
|
|
|
|
// Flex buffers are limited to 2GB, and we can't chop into 2G pieces
|
|
|
|
|
// because buffers can't end in the middle of tokens.
|
|
|
|
|
// m_buffers only applies to the "base" buffer when there's no scanBytes outstanding
|
|
|
|
|
// It won't be called on scan_buffers as they don't have yy_fill_buffer set.
|
|
|
|
|
//
|
|
|
|
|
//if (debug()) { cout<<"- pp:inputToLex ITL s="<<max_size<<" bs="<<m_bufferStack.size()<<endl; dumpSummary(); }
|
|
|
|
|
// For testing, use really small chunks
|
|
|
|
|
//if (max_size > 13) max_size=13;
|
|
|
|
|
size_t got = 0;
|
|
|
|
|
while (got < max_size // Haven't got enough
|
|
|
|
|
&& !m_buffers.empty()) { // And something buffered
|
|
|
|
|
string front = m_buffers.front(); m_buffers.pop_front();
|
|
|
|
|
size_t len = front.length();
|
|
|
|
|
if (len > (max_size-got)) { // Front string too big
|
|
|
|
|
string remainder = front.substr(max_size-got);
|
|
|
|
|
front = front.substr(0, max_size-got);
|
|
|
|
|
m_buffers.push_front(remainder); // Put back remainder for next time
|
|
|
|
|
len = (max_size-got);
|
|
|
|
|
}
|
|
|
|
|
strncpy(buf+got, front.c_str(), len);
|
|
|
|
|
got += len;
|
|
|
|
|
}
|
|
|
|
|
//if (debug()) { cout<<"- pp::inputToLex got="<<got<<" '"<<string(buf,got)<<"'"<<endl; }
|
|
|
|
|
return got;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void V3PreLex::scanBytes(const char* strp, size_t len) {
|
|
|
|
|
// Note buffers also appended in ::scanBytesBack
|
|
|
|
|
// Not "m_buffers.push_front(string(strp,len))" as we need a `define
|
|
|
|
|
// to take effect immediately, in the middle of the current buffer
|
|
|
|
|
yy_scan_bytes(strp, len);
|
2009-09-18 02:23:18 +00:00
|
|
|
|
m_bufferStack.push(currentBuffer()); // yy_scan_bytes makes new buffer
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-04-07 00:20:44 +00:00
|
|
|
|
void V3PreLex::scanBytesBack(const string& str) {
|
|
|
|
|
// Initial creation, that will pull from YY_INPUT==inputToLex
|
|
|
|
|
// Note buffers also appended in ::scanBytes
|
|
|
|
|
m_buffers.push_back(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void V3PreLex::appendDefValue(const char* textp, size_t len) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Append given text to current definition value being formed
|
|
|
|
|
m_defValue.append(textp,len);
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-18 02:23:18 +00:00
|
|
|
|
YY_BUFFER_STATE V3PreLex::currentBuffer() {
|
|
|
|
|
return YY_CURRENT_BUFFER;
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-11 15:57:43 +00:00
|
|
|
|
int V3PreLex::currentStartState() {
|
|
|
|
|
return YY_START;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void V3PreLex::lineDirective(const char* textp) {
|
|
|
|
|
m_curFilelinep->lineDirective(textp);
|
|
|
|
|
// Make sure we have a dependency on whatever file was specified
|
|
|
|
|
V3File::addSrcDepend(m_curFilelinep->filename());
|
|
|
|
|
}
|
2009-09-18 02:23:18 +00:00
|
|
|
|
|
2010-04-07 00:20:44 +00:00
|
|
|
|
void V3PreLex::dumpSummary() {
|
|
|
|
|
cout<<"- pp::dumpSummary curBuf="<<(void*)(currentBuffer())
|
|
|
|
|
<<" nBuf="<<m_bufferStack.size()
|
|
|
|
|
<<" yyfill="<<currentBuffer()->yy_fill_buffer<<endl;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-18 02:23:18 +00:00
|
|
|
|
void V3PreLex::dumpStack() {
|
|
|
|
|
// For debug use
|
2010-04-07 00:20:44 +00:00
|
|
|
|
dumpSummary();
|
2009-09-18 02:23:18 +00:00
|
|
|
|
stack<YY_BUFFER_STATE> tmpstack = m_bufferStack;
|
|
|
|
|
printf(" bufferStack[%p]:",this);
|
|
|
|
|
while (!tmpstack.empty()) {
|
|
|
|
|
printf(" %p",tmpstack.top());
|
|
|
|
|
tmpstack.pop();
|
|
|
|
|
}
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*###################################################################
|
|
|
|
|
* Local Variables:
|
|
|
|
|
* mode: C++
|
|
|
|
|
* End:
|
|
|
|
|
*/
|