/* -*- C++ -*- */
/**************************************************************************
 * DESCRIPTION: Verilator: Flex input file
 *
 * Code available from: http://www.veripool.org/verilator
 *
 **************************************************************************
 *
 * Copyright 2003-2009 by Wilson Snyder.  Verilator 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.
 *
 * 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.
 *
 *************************************************************************/

%option interactive c++ stack noyywrap
%{
/* %option nodefault */

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include "V3Number.h"
#include "V3ParseImp.h"  // Defines YYTYPE; before including bison header
#include "V3ParseBison.h"  // Generated by bison

extern void yyerror(const char*);
extern void yyerrorf(const char* format, ...);

#define STATE_VERILOG_RECENT  S05		// State name for most recent Verilog Version

#define PARSEP V3ParseImp::parsep()
#define SYMP PARSEP->symp()

#define YY_INPUT(buf,result,max_size) \
    result = PARSEP->flexPpInputToLex(buf,max_size);

//======================================================================

#define NEXTLINE() {PARSEP->incLineno();}
#define CRELINE() (PARSEP->copyOrSameFileLine())

#define FL { yylval.fl = CRELINE(); }

#define RETURN_BBOX_SYS_OR_MSG(msg,yytext) {	\
	if (!v3Global.opt.bboxSys()) yyerrorf(msg,yytext); \
	return yaD_IGNORE; }

void V3ParseImp::ppline (const char* textp) {
    // Handle `line directive
    fileline()->lineDirective(textp);
}

void V3ParseImp::verilatorCmtLint(const char* textp, bool warnOff) {
    const char* sp = textp;
    while (*sp && !isspace(*sp)) sp++;  while (*sp && isspace(*sp)) sp++;
    while (*sp && !isspace(*sp)) sp++;  while (*sp && isspace(*sp)) sp++;
    string msg = sp;
    string::size_type pos;
    if ((pos=msg.find("*")) != string::npos) { msg.erase(pos); }
    if (!(PARSEP->fileline()->warnOff(msg, warnOff))) {
	if (!PARSEP->optFuture(msg)) {
	    yyerrorf("Unknown verilator lint message code: %s, in %s",msg.c_str(), textp);
	}
    }
}

void V3ParseImp::verilatorCmtLintSave() {
    m_lintState.push_back(*PARSEP->fileline());
}
void V3ParseImp::verilatorCmtLintRestore() {
    if (m_lintState.empty()) {
	yyerrorf("/*verilator lint_restore*/ without matching save.");
	return;
    }
    PARSEP->fileline()->warnStateFrom(m_lintState.back());
    m_lintState.pop_back();
}

void V3ParseImp::verilatorCmtBad(const char* textp) {
    string cmtparse = textp;
    if (cmtparse.substr(0,strlen("/*verilator")) == "/*verilator") {
	cmtparse.replace(0,strlen("/*verilator"), "");
    }
    while (isspace(cmtparse[0])) {
	cmtparse.replace(0,1, "");
    }
    string cmtname;
    for (int i=0; isalnum(cmtparse[i]); i++) {
	cmtname += cmtparse[i];
    }
    if (!PARSEP->optFuture(cmtname)) {
	yyerrorf("Unknown verilator comment: %s",textp);
    }
}

// See V3Read.cpp
//void V3ParseImp::stateExitPsl() { BEGIN VLG; }
//void V3ParseImp::statePushVlg() { yy_push_state(VLG); }
//void V3ParseImp::statePop() { yy_pop_state(); }

//======================================================================

void yyerror(const char* errmsg) {
    PARSEP->fileline()->v3error(errmsg);
}

void yyerrorf(const char* format, ...) {
    char msg[1024];

    va_list ap;
    va_start(ap,format);
    vsprintf(msg,format,ap);
    va_end(ap);

    yyerror(msg);
}

/**********************************************************************/
%}

%e 2000
%p 5000
%n 2500
%k 1000
%a 15000
%o 25000

%s V95 V01 V05 S05
%s STRING ATTRMODE TABLE
%s PSL
%s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR
%s IGNORE

ws	[ \t\f\r]+
wsnr	[ \t\f]+
crnl	[\r]*[\n]
	/* identifier */
id	[a-zA-Z_][a-zA-Z0-9_$]*
	/* escaped identifier */
escid	\\[^ \t\f\r\n]+

%%

<INITIAL>.|\n 		{BEGIN STATE_VERILOG_RECENT; yyless(0); }

  /* Verilog 1995 */
<V95,V01,V05,S05,PSL>{
  {ws}			{ }	/* otherwise ignore white-space */
  {crnl}		{ NEXTLINE(); }		/* Count line numbers */
  /*     Extensions to Verilog set, some specified by PSL */
  "$c"[0-9]*		{ FL; return yD_C; }		/*Verilator only*/
  /*     System Tasks */
  "$display"		{ FL; return yD_DISPLAY; }
  "$fclose"		{ FL; return yD_FCLOSE; }
  "$fdisplay"		{ FL; return yD_FDISPLAY; }
  "$feof"		{ FL; return yD_FEOF; }
  "$fflush"		{ FL; return yD_FFLUSH; }
  "$fgetc"		{ FL; return yD_FGETC; }
  "$fgets"		{ FL; return yD_FGETS; }
  "$finish"		{ FL; return yD_FINISH; }
  "$fopen"		{ FL; return yD_FOPEN; }
  "$fscanf"		{ FL; return yD_FSCANF; }
  "$fullskew"		{ FL; return yaTIMINGSPEC; }
  "$fwrite"		{ FL; return yD_FWRITE; }
  "$hold"		{ FL; return yaTIMINGSPEC; }
  "$nochange"		{ FL; return yaTIMINGSPEC; }
  "$period"		{ FL; return yaTIMINGSPEC; }
  "$random"		{ FL; return yD_RANDOM; }
  "$readmemb"		{ FL; return yD_READMEMB; }
  "$readmemh"		{ FL; return yD_READMEMH; }
  "$realtime"		{ FL; return yD_TIME; }
  "$recovery"		{ FL; return yaTIMINGSPEC; }
  "$recrem"		{ FL; return yaTIMINGSPEC; }
  "$removal"		{ FL; return yaTIMINGSPEC; }
  "$setup"		{ FL; return yaTIMINGSPEC; }
  "$setuphold"		{ FL; return yaTIMINGSPEC; }
  "$sformat"		{ FL; return yD_SFORMAT; }
  "$skew"		{ FL; return yaTIMINGSPEC; }
  "$sscanf"		{ FL; return yD_SSCANF; }
  "$stime"		{ FL; return yD_STIME; }
  "$stop"		{ FL; return yD_STOP; }
  "$swrite"		{ FL; return yD_SWRITE; }
  "$test$plusargs"	{ FL; return yD_TESTPLUSARGS; }
  "$time"		{ FL; return yD_TIME; }
  "$timeskew"		{ FL; return yaTIMINGSPEC; }
  "$value$plusargs"	{ FL; return yD_VALUEPLUSARGS; }
  "$width"		{ FL; return yaTIMINGSPEC; }
  "$write"		{ FL; return yD_WRITE; }
  /*     Keywords */
  "always"		{ FL; return yALWAYS; }
  "and"			{ FL; return yAND; }
  "assign"		{ FL; return yASSIGN; }
  "begin"		{ FL; return yBEGIN; }
  "buf"			{ FL; return yBUF; }
  "bufif0"		{ FL; return yBUFIF0; }
  "bufif1"		{ FL; return yBUFIF1; }
  "case"		{ FL; return yCASE; }
  "casex"		{ FL; return yCASEX; }
  "casez"		{ FL; return yCASEZ; }
  "default"		{ FL; return yDEFAULT; }
  "defparam"		{ FL; return yDEFPARAM; }
  "disable"		{ FL; return yDISABLE; }
  "edge"		{ FL; return yaTIMINGSPEC; }
  "else"		{ FL; return yELSE; }
  "end"			{ FL; return yEND; }
  "endcase"		{ FL; return yENDCASE; }
  "endfunction"		{ FL; return yENDFUNCTION; }
  "endmodule"		{ FL; return yENDMODULE; }
  "endprimitive"	{ FL; return yENDPRIMITIVE; }
  "endspecify"		{ FL; return yENDSPECIFY; }
  "endtable"		{ yyerrorf("Syntax error: ENDTABLE outside of TABLE"); }
  "endtask"		{ FL; return yENDTASK; }
  "for"			{ FL; return yFOR; }
  "forever"		{ FL; return yFOREVER; }
  "function"		{ FL; return yFUNCTION; }
  "if"			{ FL; return yIF; }
  "initial"		{ FL; return yINITIAL; }
  "inout"		{ FL; return yINOUT; }
  "input"		{ FL; return yINPUT; }
  "integer"		{ FL; return yINTEGER; }
  "macromodule"		{ FL; return yMODULE; }
  "module"		{ FL; return yMODULE; }
  "nand"		{ FL; return yNAND; }
  "negedge"		{ FL; return yNEGEDGE; }
  "nor"			{ FL; return yNOR; }
  "not"			{ FL; return yNOT; }
  "notif0"		{ FL; return yNOTIF0; }
  "notif1"		{ FL; return yNOTIF1; }
  "or"			{ FL; return yOR; }
  "output"		{ FL; return yOUTPUT; }
  "parameter"		{ FL; return yPARAMETER; }
  "posedge"		{ FL; return yPOSEDGE; }
  "primitive"		{ FL; return yPRIMITIVE; }
  "pulldown"		{ FL; return yPULLDOWN; }
  "pullup"		{ FL; return yPULLUP; }
  "reg"			{ FL; return yREG; }
  "repeat"		{ FL; return yREPEAT; }
  "scalared"		{ FL; return ySCALARED; }
  "specify"		{ FL; return ySPECIFY; }
  "specparam"		{ FL; return ySPECPARAM; }
  "supply0"		{ FL; return ySUPPLY0; }
  "supply1"		{ FL; return ySUPPLY1; }
  "table"		{ yy_push_state(TABLE); FL; return yTABLE; }
  "task"		{ FL; return yTASK; }
  "time"		{ FL; return yTIME; }
  "tri"			{ FL; return yTRI; }
  "vectored"		{ FL; return yVECTORED; }
  "while"		{ FL; return yWHILE; }
  "wire"		{ FL; return yWIRE; }
  "xnor"		{ FL; return yXNOR; }
  "xor"			{ FL; return yXOR; }
  /*     Special errors */
  "$displayb"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $display with %%b format instead: %s",yytext); }
  "$displayh"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $display with %%x format instead: %s",yytext); }
  "$displayo"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $display with %%o format instead: %s",yytext); }
  "$fdisplayb"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fdisplay with %%b format instead: %s",yytext); }
  "$fdisplayh"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fdisplay with %%x format instead: %s",yytext); }
  "$fdisplayo"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fdisplay with %%o format instead: %s",yytext); }
  "$fwriteb"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fwrite with %%b format instead: %s",yytext); }
  "$fwriteh"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fwrite with %%x format instead: %s",yytext); }
  "$fwriteo"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fwrite with %%o format instead: %s",yytext); }
  "$writeb"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $write with %%b format instead: %s",yytext); }
  "$writeh"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $write with %%x format instead: %s",yytext); }
  "$writeo"		{ FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $write with %%o format instead: %s",yytext); }
  /*     Generic unsupported warnings */
  "cmos"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "deassign"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "event"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "force"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "fork"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "highz0"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "highz1"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "join"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "large"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "medium"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "nmos"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "pmos"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "pull0"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "pull1"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "rcmos"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "real"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "realtime"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "release"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "rnmos"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "rpmos"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "rtran"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "rtranif0"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "rtranif1"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "small"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "strong0"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "strong1"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "tran"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "tranif0"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "tranif1"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "triand"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "trior"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "trireg"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "tri0"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "tri1"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "wait"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "wand"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "weak0"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "weak1"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "wor"			{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
}

  /* Verilog 2001 */
<V01,V05,S05,PSL>{
  /*     System Tasks */
  "$signed"		{ FL; return yD_SIGNED; }
  "$unsigned"		{ FL; return yD_UNSIGNED; }
  /*     Keywords */
  "automatic"		{ FL; return yAUTOMATIC; }
  "endgenerate"		{ FL; return yENDGENERATE; }
  "generate"		{ FL; return yGENERATE; }
  "genvar"		{ FL; return yGENVAR; }
  "ifnone"		{ FL; return yaTIMINGSPEC; }
  "localparam"		{ FL; return yLOCALPARAM; }
  "noshowcancelled"	{ FL; return yaTIMINGSPEC; }
  "pulsestyle_ondetect"	{ FL; return yaTIMINGSPEC; }
  "pulsestyle_onevent"	{ FL; return yaTIMINGSPEC; }
  "showcancelled"	{ FL; return yaTIMINGSPEC; }
  "signed"		{ FL; return ySIGNED; }
  "unsigned"		{ FL; return yUNSIGNED; }
  /*     Generic unsupported keywords */
  "cell"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
  "config"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
  "design"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
  "endconfig"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
  "incdir"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
  "include"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented; probably you want `include instead: %s",yytext); }
  "instance"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
  "liblist"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
  "library"		{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
  "use"			{ yyerrorf("Unsupported: Verilog 2001-config reserved word not implemented: %s",yytext); }
}

  /* Verilog 2005 */
<V05,S05,PSL>{
  /*     Keywords */
  "uwire"		{ FL; return yWIRE; }
}

  /* System Verilog 2005 */
<S05,PSL>{
  /*     System Tasks */
  "$bits"		{ FL; return yD_BITS; }
  "$clog2"		{ FL; return yD_CLOG2; }
  "$countones"		{ FL; return yD_COUNTONES; }
  "$error"		{ FL; return yD_ERROR; }
  "$fatal"		{ FL; return yD_FATAL; }
  "$info"		{ FL; return yD_INFO; }
  "$isunknown"		{ FL; return yD_ISUNKNOWN; }
  "$onehot"		{ FL; return yD_ONEHOT; }
  "$onehot0"		{ FL; return yD_ONEHOT0; }
  "$warning"		{ FL; return yD_WARNING; }
  /*     SV2005 Keywords */
  "$unit"		{ FL; return yD_UNIT; }  /* Yes, a keyword, not task */
  "always_comb"		{ FL; return yALWAYS; }
  "always_ff"		{ FL; return yALWAYS; }
  "always_latch"	{ FL; return yALWAYS; }
  "bit"			{ FL; return yBIT; }
  "byte"		{ FL; return yBYTE; }
  "chandle"		{ FL; return yCHANDLE; }
  "clocking"		{ FL; return yCLOCKING; }
  "context"		{ FL; return yCONTEXT; }
  "do"			{ FL; return yDO; }
  "endclocking"		{ FL; return yENDCLOCKING; }
  "endpackage"		{ FL; return yENDPACKAGE; }
  "endprogram"		{ FL; return yENDPROGRAM; }
  "endproperty"		{ FL; return yENDPROPERTY; }
  "export"		{ FL; return yEXPORT; }
  "final"		{ FL; return yFINAL; }
  "iff"			{ FL; return yIFF; }
  "import"		{ FL; return yIMPORT; }
  "int"			{ FL; return yINT; }
  "logic"		{ FL; return yLOGIC; }
  "longint"		{ FL; return yLONGINT; }
  "package"		{ FL; return yPACKAGE; }
  "priority"		{ FL; return yPRIORITY; }
  "program"		{ FL; return yPROGRAM; }
  "pure"		{ FL; return yPURE; }
  "shortint"		{ FL; return ySHORTINT; }
  "static"		{ FL; return ySTATIC; }
  "string"		{ FL; return ySTRING; }
  "timeprecision"	{ FL; return yTIMEPRECISION; }
  "timeunit"		{ FL; return yTIMEUNIT; }
  "typedef"		{ FL; return yTYPEDEF; }
  "unique"		{ FL; return yUNIQUE; }
  "var"			{ FL; return yVAR; }
  "void"		{ FL; return yVOID; }
  /*     Generic unsupported warnings */
  /* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */
  "$root"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "alias"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "bind"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "bins"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "binsof"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "break"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "class"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "constraint"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "continue"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "covergroup"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "coverpoint"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "cross"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "dist"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "endclass"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "endgroup"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "endinterface"	{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "endsequence"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "enum"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "expect"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "extends"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "extern"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "first_match"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "foreach"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "forkjoin"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "ignore_bins"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "illegal_bins"	{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "inside"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "interface"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "intersect"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "join_any"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "join_none"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "local"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "matches"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "modport"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "new"			{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "null"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "packed"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "protected"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "rand"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "randc"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "randcase"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "randomize"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "randsequence"	{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "ref"			{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "return"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "shortreal"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "solve"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "struct"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "super"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "tagged"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "this"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "throughout"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "type"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "virtual"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "wait_order"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "wildcard"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "with"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
}

  /* SystemVerilog ONLY not PSL; different rules for PSL as specified below */
<S05>{
  /*     Keywords */
  "assert"		{ FL; return yASSERT; }
  "cover"		{ FL; return yCOVER; }
  "property"		{ FL; return yPROPERTY; }
  /*     Generic unsupported warnings */
  "assume"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
  "before"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
  "const"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
  "sequence"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
  "union"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
  "within"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
}

  /* Default PLI rule */
<V95,V01,V05,S05,PSL>{
  "$"[a-zA-Z_$][a-zA-Z0-9_$]*	{ string str (yytext,yyleng);
				  yylval.strp = PARSEP->newString(AstNode::encodeName(str));
				  // Lookup unencoded name including the $, to avoid hitting normal signals
				  if (SYMP->symCurrentp()->findIdUpward(str)) {
				      FL; return yaD_DPI;
				  } else { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported or unknown PLI call: %s",yytext); }
				}
}

  /************************************************************************/
  /* PSL */

  /*Entry into PSL; mode change */
<V95,V01,V05,S05>{
  "psl"			{ yy_push_state(PSL); FL; return yPSL; }
}

<PSL>{
  /*     Special things */
  "psl"			{ ; }	// 'psl' may occur in middle of statement, so easier just to suppress
  /*     Keywords */
  "assert"		{ FL; return yPSL_ASSERT; }
  "assume"		{ FL; return yPSL_ASSERT; } //==assert
  "before_!"		{ yyerrorf("Illegal syntax, use before!_ instead of %s",yytext); }
  "clock"		{ FL; return yPSL_CLOCK; }
  "countones"		{ FL; return yD_COUNTONES; }
  "cover"		{ FL; return yPSL_COVER; }
  "isunknown"		{ FL; return yD_ISUNKNOWN; }
  "onehot"		{ FL; return yD_ONEHOT; }
  "onehot0"		{ FL; return yD_ONEHOT0; }
  "until_!"		{ yyerrorf("Illegal syntax, use until!_ instead of %s",yytext); }
  "report"		{ FL; return yPSL_REPORT; }
  "true"		{ FL; return yTRUE; }
  /*     Generic unsupported warnings */
  /*"A"			{ yyerrorf("Unsupported: PSL branching reserved word not implemented: %s",yytext); } */
  /*"AF"		{ yyerrorf("Unsupported: PSL branching reserved word not implemented: %s",yytext); } */
  /*"AG"		{ yyerrorf("Unsupported: PSL branching reserved word not implemented: %s",yytext); } */
  /*"AX"		{ yyerrorf("Unsupported: PSL branching reserved word not implemented: %s",yytext); } */
  /*"E"			{ yyerrorf("Unsupported: PSL branching reserved word not implemented: %s",yytext); } */
  /*"EF"		{ yyerrorf("Unsupported: PSL branching reserved word not implemented: %s",yytext); } */
  /*"EG"		{ yyerrorf("Unsupported: PSL branching reserved word not implemented: %s",yytext); } */
  /*"EX"		{ yyerrorf("Unsupported: PSL branching reserved word not implemented: %s",yytext); } */
  /*"F"			{ FL; return yEVENTUALLYB; } */
  /*"G"			{ FL; return yALWAYS; } */
  /*"U"			{ FL; return yUNTILB; } */
  /*"W"			{ FL; return yUNTIL; } */
  /*"X"			{ FL; return yNEXT; } */
  /*"X!"		{ FL; return yNEXTB; } */
  "%for"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "%if"			{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "abort"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "assume_guarantee"	{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); } //Unsup in other tools
  "before"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "before!"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "before!_"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "before_"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "boolean"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "const"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "endpoint"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "eventually!"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "fairness"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); } //Unsup in other tools
  "fell"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "forall"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); } //Unsup in other tools
  "in"			{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "inf"			{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "inherit"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); } //Unsup in other tools
  "never"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next!"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_a"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_a!"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_e"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_e!"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_event"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_event!"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_event_a"	{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_event_a!"	{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_event_e"	{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "next_event_e!"	{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "prev"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "property"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "restrict"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "restrict_guarantee"	{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); } //Unsup in other tools
  "rose"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "sequence"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "stable"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "strong"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); } //Unsup in other tools
  "union"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "until"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "until!"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "until!_"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "until_"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "vmode"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); } //Unsup in other tools
  "vprop"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); } //Unsup in other tools
  "vunit"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
  "within"		{ yyerrorf("Unsupported: PSL reserved word not implemented: %s",yytext); }
}

  /************************************************************************/
  /* Meta comments */

  /* Converted from //{cmt}verilator ...{cmt} by preprocessor */
<V95,V01,V05,S05,PSL>{
  "/*verilator"{ws}*"*/"		{}	/* Ignore empty comments, may be `endif // verilator */
  "/*verilator clock_enable*/"		{ FL; return yVL_CLOCK_ENABLE; }
  "/*verilator coverage_block_off*/"	{ FL; return yVL_COVERAGE_BLOCK_OFF; }
  "/*verilator full_case*/"		{ FL; return yVL_FULL_CASE; }
  "/*verilator inline_module*/"		{ FL; return yVL_INLINE_MODULE; }
  "/*verilator isolate_assignments*/"	{ FL; return yVL_ISOLATE_ASSIGNMENTS; }
  "/*verilator no_inline_module*/"	{ FL; return yVL_NO_INLINE_MODULE; }
  "/*verilator no_inline_task*/"	{ FL; return yVL_NO_INLINE_TASK; }
  "/*verilator parallel_case*/"		{ FL; return yVL_PARALLEL_CASE; }
  "/*verilator public*/"		{ FL; return yVL_PUBLIC; }
  "/*verilator public_flat*/"		{ FL; return yVL_PUBLIC_FLAT; }
  "/*verilator public_module*/"		{ FL; return yVL_PUBLIC_MODULE; }
  "/*verilator sc_clock*/"		{ FL; return yVL_CLOCK; }
  "/*verilator systemc_clock*/"		{ FL; return yVL_CLOCK; }
  "/*verilator tracing_off*/"		{PARSEP->fileline()->tracingOn(false); }
  "/*verilator tracing_on*/"		{PARSEP->fileline()->tracingOn(true); }
  "/*verilator coverage_off*/"		{PARSEP->fileline()->coverageOn(false); }
  "/*verilator coverage_on*/"		{PARSEP->fileline()->coverageOn(true); }
  "/*verilator lint_off"[^*]*"*/"	{PARSEP->verilatorCmtLint(yytext, true); }
  "/*verilator lint_on"[^*]*"*/"	{PARSEP->verilatorCmtLint(yytext, false); }
  "/*verilator lint_restore*/"		{PARSEP->verilatorCmtLintRestore(); }
  "/*verilator lint_save*/"		{PARSEP->verilatorCmtLintSave(); }

  "/*"[^*]*"*/"				{PARSEP->verilatorCmtBad(yytext); }
}

  /************************************************************************/

  /* Single character operator thingies */
<V95,V01,V05,S05>{
  "{"			{ FL; return yytext[0]; }
  "}"			{ FL; return yytext[0]; }
}
<V95,V01,V05,S05,PSL>{
  "!"			{ FL; return yytext[0]; }
  "#"			{ FL; return yytext[0]; }
  "$"			{ FL; return yytext[0]; }
  "%"			{ FL; return yytext[0]; }
  "&"			{ FL; return yytext[0]; }
  "("			{ FL; return yytext[0]; }
  ")"			{ FL; return yytext[0]; }
  "*"			{ FL; return yytext[0]; }
  "+"			{ FL; return yytext[0]; }
  ","			{ FL; return yytext[0]; }
  "-"			{ FL; return yytext[0]; }
  "."			{ FL; return yytext[0]; }
  "/"			{ FL; return yytext[0]; }
  ":"			{ FL; return yytext[0]; }
  ";"			{ FL; return yytext[0]; }
  "<"			{ FL; return yytext[0]; }
  "="			{ FL; return yytext[0]; }
  ">"			{ FL; return yytext[0]; }
  "?"			{ FL; return yytext[0]; }
  "@"			{ FL; return yytext[0]; }
  "["			{ FL; return yytext[0]; }
  "]"			{ FL; return yytext[0]; }
  "^"			{ FL; return yytext[0]; }
  "|"			{ FL; return yytext[0]; }
  "~"			{ FL; return yytext[0]; }
}

  /************************************************************************/
  /* Operators and multi-character symbols */

  /* Verilog 1995 Operators */
<V95,V01,V05,S05,PSL>{
  "&&"			{ FL; return yP_ANDAND; }
  "||"			{ FL; return yP_OROR; }
  "<="			{ FL; return yP_LTE; }
  ">="			{ FL; return yP_GTE; }
  "<<"			{ FL; return yP_SLEFT; }
  ">>"			{ FL; return yP_SRIGHT; }
  "=="			{ FL; return yP_EQUAL; }
  "!="			{ FL; return yP_NOTEQUAL; }
  "==="			{ FL; return yP_CASEEQUAL; }
  "!=="			{ FL; return yP_CASENOTEQUAL; }
  "^~"			{ FL; return yP_XNOR; }
  "~^"			{ FL; return yP_XNOR; }
  "~&"			{ FL; return yP_NAND; }
  "~|"			{ FL; return yP_NOR; }
  "->"			{ FL; return yP_MINUSGT; }
  "=>"			{ FL; return yP_EQGT; }
  "*>"			{ FL; return yP_ASTGT; }
  "&&&"			{ FL; return yP_ANDANDAND; }
}

  /* Verilog 2001 Operators */
<V01,V05,S05,PSL>{
  "<<<"			{ FL; return yP_SLEFT; }
  ">>>"			{ FL; return yP_SSRIGHT; }
  "**"			{ FL; return yP_POW; }
  "+:"			{ FL; return yP_PLUSCOLON; }
  "-:"			{ FL; return yP_MINUSCOLON; }
  ".*"			{ FL; return yP_DOTSTAR; }
}

  /* SystemVerilog Operators */
<S05>{
  "'"			{ FL; return yP_TICK; }
  "'{"			{ FL; return yP_TICKBRA; }
  "==?"			{ FL; return yP_WILDEQUAL; }
  "!=?"			{ FL; return yP_WILDNOTEQUAL; }
  "++"			{ FL; return yP_PLUSPLUS; }
  "--"			{ FL; return yP_MINUSMINUS; }
  "+="			{ FL; return yP_PLUSEQ; }
  "-="			{ FL; return yP_MINUSEQ; }
  "*="			{ FL; return yP_TIMESEQ; }
  "/="			{ FL; return yP_DIVEQ; }
  "%="			{ FL; return yP_MODEQ; }
  "&="			{ FL; return yP_ANDEQ; }
  "|="			{ FL; return yP_OREQ; }
  "^="			{ FL; return yP_XOREQ; }
  "<<="			{ FL; return yP_SLEFTEQ; }
  ">>="			{ FL; return yP_SRIGHTEQ; }
  "<<<="		{ FL; return yP_SLEFTEQ; }
  ">>>="		{ FL; return yP_SSRIGHTEQ; }
  "->>"			{ FL; return yP_MINUSGTGT; }
  "##"			{ FL; return yP_POUNDPOUND; }
  "@@"			{ FL; return yP_ATAT; }
  "::"			{ FL; return yP_COLONCOLON; }
  ":="			{ FL; return yP_COLONEQ; }
  ":/"[^\/\*]		{ FL; return yP_COLONDIV; }  /* : then comment is not ":/" */
  "|->"			{ FL; return yP_ORMINUSGT; }
  "|=>"			{ FL; return yP_OREQGT; }
  /* Some simulators allow whitespace here. Grr */
  "["{ws}*"*"		{ FL; return yP_BRASTAR; }
  "["{ws}*"="		{ FL; return yP_BRAEQ; }
  "["{ws}*"->"		{ FL; return yP_BRAMINUSGT; }
}

  /* PSL Operators */
<PSL>{
  "{"			{ FL; return yPSL_BRA; }	// Avoid parser hitting concatenate.
  "}"			{ FL; return yPSL_KET; }	// Avoid parser hitting concatenate.
  "<->"			{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } //Unsup in other tools
  "[*"			{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } // yP_BRA_STAR
  "[*]"			{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } // yP_BRA_STAR_KET
  "[+]"			{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } // yP_BRA_PLUS_KET
  "[->"			{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } // yP_BRA_MINUS_GT
  "[->]"		{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } // yP_BRA_MINUS_GT_KET
  "[="			{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } // yP_BRA_EQ
  "|->"			{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } // yP_ORMINUSGT
  "|=>"			{ yyerrorf("Unsupported: PSL operator not implemented: %s",yytext); } // yP_OREQGT
}

  /* Identifiers and numbers */
<V95,V01,V05,S05,PSL>{
  {escid}		{ FL; yylval.strp = PARSEP->newString
	  			(AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash
			  return yaID__LEX;
			}
  {id}			{ FL; yylval.strp = PARSEP->newString(AstNode::encodeName(string(yytext)));
			  return yaID__LEX;
			}
  \"[^\"\\]*\"		{ FL; yylval.strp = PARSEP->newString(yytext+1,yyleng-2);
			  return yaSTRING;
			}
  \" 			{ yy_push_state(STRING); yymore(); }

  [0-9]*?['']s?[bcodhBCODH][ \t]*[A-Fa-f0-9xXzZ_?]*	{
			  FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext);
                          return yaINTNUM;
			}
  [0-9]*?['']s?[01xXzZ]	{	/* SystemVerilog */
			  FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext);
                          return yaINTNUM;
			}
  /* Note below is constructed to not match the ' that begins a '(  or '{ */
  [0-9][_0-9]*[ \t]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+	{
			  FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext);
                          return yaINTNUM;
			}
  [0-9][_0-9]*[ \t]*['']s?[bcodhBCODH]	{
			  FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext);
                          return yaINTNUM;
			}
  [0-9][_0-9]*[ \t]*['']s	{
			  FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext);
                          return yaINTNUM;
			}
  [0-9][_0-9]*		{
			  FL; yylval.nump = PARSEP->newNumber(PARSEP->fileline(),(char*)yytext);
                          return yaINTNUM;
			}
  [0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? {
			  FL; yylval.cdouble = 0;  /* Only for delays, not used yet */
                          return yaFLOATNUM;
			}
  [0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) {
			  FL; yylval.cdouble = 0;  /* Only for delays, not used yet */
                          return yaFLOATNUM;
			}
  [0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) {
			  FL; yylval.cdouble = 0;  /* Only for times, not used yet */
                          return yaTIMENUM;
			}
}

  /************************************************************************/
  /* STRINGS */
<STRING><<EOF>>		{ yyerrorf("EOF in unterminated string"); yyleng = 0; yy_pop_state(); }
<STRING>{crnl}		{ yyerrorf("Unterminated string"); NEXTLINE(); }
<STRING>\\{crnl}	{ yymore(); NEXTLINE(); }
<STRING>\\.	 	{ yymore(); }
<STRING>\" 		{ yy_pop_state();
			  FL; yylval.strp = PARSEP->newString(yytext+1,yyleng-2);
			  return yaSTRING; }
<STRING>.		{ yymore(); }

  /************************************************************************/
  /* Attributes */
<ATTRMODE>{crnl}	{ yymore(); NEXTLINE(); }
<ATTRMODE>"*)"		{ yy_pop_state(); }
<ATTRMODE>. 		{ yymore(); }
<ATTRMODE><<EOF>>	{ yyerrorf("EOF in (*");
			  yyleng = 0; yy_pop_state(); }

  /************************************************************************/
  /* Attributes */
<V95,V01,V05,S05>{
    "(*"/{ws}*[^)]	{ yymore(); yy_push_state(ATTRMODE); }	// Doesn't match (*)
}

  /************************************************************************/
  /* Tables */
<TABLE>\\{crnl}		{ yymore(); NEXTLINE(); }
<TABLE>{crnl}		{ NEXTLINE(); yymore(); }
<TABLE>";"		{ yylval.strp = PARSEP->newString(yytext,yyleng); return yaTABLELINE; }
<TABLE>"endtable"	{ yy_pop_state(); FL; return yENDTABLE; }
<TABLE>. 		{ yymore(); }
<TABLE><<EOF>>		{ yyerrorf("EOF in TABLE"); yyleng = 0; yy_pop_state(); }

  /************************************************************************/
  /* Preprocessor */
  /* Common for all SYSC header states */
  /* OPTIMIZE: we return one per line, make it one for the entire block */
<V95,V01,V05,S05,PSL,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
  "`accelerate"				{ } // Verilog-XL compatibility
  "`autoexpand_vectornets"		{ } // Verilog-XL compatibility
  "`celldefine"				{ PARSEP->inCellDefine(true); }
  "`default_decay_time"{ws}+[^\n\r]*	{ } // Verilog spec - delays only
  "`default_nettype"{ws}+[a-zA-Z0-9]*	{ yyerrorf("Unsupported: Verilog 2001 directive not implemented: %s",yytext); } // Verilog 2001
  "`delay_mode_distributed"		{ } // Verilog spec - delays only
  "`delay_mode_path"			{ } // Verilog spec - delays only
  "`delay_mode_unit"			{ } // Verilog spec - delays only
  "`delay_mode_zero"			{ } // Verilog spec - delays only
  "`disable_portfaults"			{ } // Verilog-XL compatibility
  "`enable_portfaults"			{ } // Verilog-XL compatibility
  "`endcelldefine"			{ PARSEP->inCellDefine(false); }
  "`endprotect"				{ }
  "`expand_vectornets"			{ } // Verilog-XL compatibility
  "`inline"				{ }
  "`line"{ws}+[^\n\r]*{crnl}		{ PARSEP->ppline(yytext); }
  "`noaccelerate"			{ } // Verilog-XL compatibility
  "`noexpand_vectornets"		{ } // Verilog-XL compatibility
  "`noremove_gatenames"			{ } // Verilog-XL compatibility
  "`noremove_netnames"			{ } // Verilog-XL compatibility
  "`nosuppress_faults"			{ } // Verilog-XL compatibility
  "`nounconnected_drive"		{ } // Verilog-XL compatibility
  "`portcoerce"				{ }
  "`pragma"{ws}+[^\n\r]*		{ } // Verilog 2005
  "`protect"				{ }
  "`psl"				{ if (PARSEP->optPsl()) { BEGIN PSL; } else { BEGIN IGNORE; } }
  "`remove_gatenames"			{ } // Verilog-XL compatibility
  "`remove_netnames"			{ } // Verilog-XL compatibility
  "`resetall"				{ }
  "`suppress_faults"			{ } // Verilog-XL compatibility
  "`timescale"{ws}+[^\n\r]*		{ } // Verilog spec - not supported

  /* See also setLanguage below */
  "`begin_keywords"[ \t]*\"1364-1995\"		{ yy_push_state(V95); PARSEP->pushBeginKeywords(YY_START); }
  "`begin_keywords"[ \t]*\"1364-2001\"		{ yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); }
  "`begin_keywords"[ \t]*\"1364-2001-noconfig\"	{ yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); }
  "`begin_keywords"[ \t]*\"1364-2005\"		{ yy_push_state(V05); PARSEP->pushBeginKeywords(YY_START); }
  "`begin_keywords"[ \t]*\"1800-2005\"		{ yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); }
  "`end_keywords"				{ yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }

  /* Verilator */
  "`systemc_ctor"			{ BEGIN SYSCCTOR; }
  "`systemc_dtor"			{ BEGIN SYSCDTOR; }
  "`systemc_header"			{ BEGIN SYSCHDR; }
  "`systemc_imp_header"			{ BEGIN SYSCIMPH; }
  "`systemc_implementation"		{ BEGIN SYSCIMP; }
  "`systemc_interface"			{ BEGIN SYSCINT; }
  "`verilog"				{ BEGIN PARSEP->lastVerilogState(); }
}

<SYSCHDR>[ \t]*[^` \t\n\r][^\n\r]*{crnl}	{ FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCHDR; }
<SYSCINT>[ \t]*[^` \t\n\r][^\n\r]*{crnl}	{ FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCINT; }
<SYSCIMP>[ \t]*[^` \t\n\r][^\n\r]*{crnl}	{ FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCIMP; }
<SYSCIMPH>[ \t]*[^` \t\n\r][^\n\r]*{crnl}	{ FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCIMPH; }
<SYSCCTOR>[ \t]*[^` \t\n\r][^\n\r]*{crnl}	{ FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCCTOR; }
<SYSCDTOR>[ \t]*[^` \t\n\r][^\n\r]*{crnl}	{ FL; NEXTLINE(); yylval.strp = PARSEP->newString(yytext); return yaSCDTOR; }
<IGNORE>[ \t]*[^` \t\n\r][^\n\r]*{crnl}		{ NEXTLINE(); }

  /* Pick up text-type data */
<SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
  {wsnr}*		{ yymore(); }
  {crnl}		{ NEXTLINE(); yymore(); }
}

  /************************************************************************/
  /* Default rules - leave last */

<V95,V01,V05,S05,PSL>{
  "`"[a-zA-Z_0-9]+	{ FL; yyerrorf("Define or directive not defined: %s",yytext); }
  "//"[^\n]*		{ }  /* throw away single line comments */
  .			{ FL; return yytext[0]; }	/* return single char ops. */
}

  /* Catch all - absolutely last */
<*>.|\n     		{ yyerrorf("Missing verilog.l rule: Default rule invoked in state %d: %s", YY_START, yytext); }
%%
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }

int V3ParseImp::lexToken() {
    // called from lexToBison, has a "this"
    // yylvalp is global
    int token = yylexThis();
    if (token == yaID__LEX) {
	AstNode* scp;
	if (V3SymTable* look_underp = SYMP->nextId()) {
	    if (debugFlex()) { cout<<"   lexToken: next id lookup forced under "<<look_underp<<endl; }
	    scp = look_underp->findIdUpward(*(yylval.strp));
	    // "consume" it.  Must set again if want another token under temp scope
	    SYMP->nextId(NULL);
	} else {
	    UINFO(7,"   lexToken: find upward "<<SYMP->symCurrentp()<<" for '"<<*(yylval.strp)<<"'"<<endl);
	    //if (debug()>=9) SYMP->symCurrentp()->dump(cout,"     -findtree: ",true);
	    scp = SYMP->symCurrentp()->findIdUpward(*(yylval.strp));
	}
	yylval.scp = scp;
	if (scp) {
	    UINFO(7,"   lexToken: Found "<<scp<<endl);
	    if (scp->castTypedef())		token = yaID__aTYPE;
	    else if (scp->castTypedefFwd())	token = yaID__aTYPE;
	    else if (scp->castPackage()) 	token = yaID__aPACKAGE;
	    //UNSUP else if (scp->castClass()) 		token = yaID__aCLASS;
	    //UNSUP else if (scp->castCoverGroup()) 	token = yaID__aCOVERGROUP;
	    else token = yaID__ETC;
	} else {  // Not found
	    token = yaID__ETC;
	}
    }
    return token;
}

int V3ParseImp::lexToBison() {
    // Called as global since bison doesn't have our pointer
    int tok = lexToken();
    //yylval.scp = NULL;   // Symbol table not yet needed - no packages
    if (debugFlex()>=6 || debugBison()>=6) {
	cout<<"   lexToBison  TOKEN="<<tok<<" "<<tokenName(tok);
	if (tok == yaID__ETC || tok == yaID__LEX || tok == yaID__aTYPE) {
	    cout<<"   strp='"<<*(yylval.strp)<<"'";
	}
	cout<<endl;
    }
    return tok;
}

