/* -*- C++ -*- */
/**************************************************************************
 * DESCRIPTION: Verilator: Flex input file
 *
 * Code available from: http://www.veripool.org/verilator
 *
 **************************************************************************
 *
 * Copyright 2003-2016 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  S12		// 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->linenoInc();}
#define LINECHECKS(textp,len)  { const char* cp=textp; for (int n=len; n; --n) if (cp[n]=='\n') NEXTLINE(); }
#define LINECHECK()  LINECHECKS(yytext,yyleng)
#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
    int enterExit;
    fileline()->lineDirective(textp, enterExit/*ref*/);
}

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::statePop() { yy_pop_state(); }

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

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

void yyerrorf(const char* format, ...) {
    const int maxlen = 2000;
    char msg[maxlen];

    va_list ap;
    va_start(ap,format);
    VL_VSNPRINTF(msg,maxlen,format,ap);
    msg[maxlen-1] = '\0';
    va_end(ap);

    yyerror(msg);
}

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

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

%s V95 V01 V05 S05 S09 S12
%s STRING ATTRMODE TABLE
%s VA5 SAX VLT
%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]+
word	[a-zA-Z0-9_]+
	/* verilog numbers, constructed to not match the ' that begins a '(  or '{ */
vnum1	[0-9]*?['']s?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]*
vnum2	[0-9]*?['']s?[01xXzZ]
vnum3	[0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+
vnum4	[0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]
vnum5	[0-9][_0-9]*[ \t\n]*['']s
vnum	{vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}

%%

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

  /************************************************************************/
  /* Verilator control files */
<VLT>{
  {ws}			{ }	/* otherwise ignore white-space */
  {crnl}		{ NEXTLINE(); }		/* Count line numbers */

  "coverage_off"	{ FL; return yVLT_COVERAGE_OFF; }
  "coverage_on"		{ FL; return yVLT_COVERAGE_ON; }
  "lint_off"		{ FL; return yVLT_LINT_OFF; }
  "lint_on"		{ FL; return yVLT_LINT_ON; }
  "tracing_off"		{ FL; return yVLT_TRACING_OFF; }
  "tracing_on"		{ FL; return yVLT_TRACING_ON; }

  -?"-file"		{ FL; return yVLT_D_FILE; }
  -?"-lines"		{ FL; return yVLT_D_LINES; }
  -?"-msg"		{ FL; return yVLT_D_MSG; }
}

  /************************************************************************/
  /* Verilog 1995 */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
  {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 */
  "$bitstoreal"		{ FL; return yD_BITSTOREAL; }
  "$ceil"		{ FL; return yD_CEIL; }
  "$display"		{ FL; return yD_DISPLAY; }
  "$exp"		{ FL; return yD_EXP; }
  "$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; }
  "$floor"		{ FL; return yD_FLOOR; }
  "$fopen"		{ FL; return yD_FOPEN; }
  "$fscanf"		{ FL; return yD_FSCANF; }
  "$fullskew"		{ FL; return yaTIMINGSPEC; }
  "$fwrite"		{ FL; return yD_FWRITE; }
  "$hold"		{ FL; return yaTIMINGSPEC; }
  "$itor"		{ FL; return yD_ITOR; }
  "$ln"			{ FL; return yD_LN; }
  "$log10"		{ FL; return yD_LOG10; }
  "$nochange"		{ FL; return yaTIMINGSPEC; }
  "$period"		{ FL; return yaTIMINGSPEC; }
  "$pow"		{ FL; return yD_POW; }
  "$random"		{ FL; return yD_RANDOM; }
  "$readmemb"		{ FL; return yD_READMEMB; }
  "$readmemh"		{ FL; return yD_READMEMH; }
  "$realtime"		{ FL; return yD_REALTIME; }
  "$realtobits"		{ FL; return yD_REALTOBITS; }
  "$recovery"		{ FL; return yaTIMINGSPEC; }
  "$recrem"		{ FL; return yaTIMINGSPEC; }
  "$removal"		{ FL; return yaTIMINGSPEC; }
  "$rtoi"		{ FL; return yD_RTOI; }
  "$setup"		{ FL; return yaTIMINGSPEC; }
  "$setuphold"		{ FL; return yaTIMINGSPEC; }
  "$sformat"		{ FL; return yD_SFORMAT; }
  "$sformatf"		{ FL; return yD_SFORMATF; }
  "$skew"		{ FL; return yaTIMINGSPEC; }
  "$sqrt"		{ FL; return yD_SQRT; }
  "$sscanf"		{ FL; return yD_SSCANF; }
  "$stime"		{ FL; return yD_STIME; }
  "$stop"		{ FL; return yD_STOP; }
  "$swrite"		{ FL; return yD_SWRITE; }
  "$system"		{ FL; return yD_SYSTEM; }
  "$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; }
  "cmos"		{ FL; return yCMOS; }
  "default"		{ FL; return yDEFAULT; }
  "defparam"		{ FL; return yDEFPARAM; }
  "disable"		{ FL; return yDISABLE; }
  "edge"		{ FL; return yEDGE; }
  "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; }
  "nmos"		{ FL; return yNMOS; }
  "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; }
  "pmos"		{ FL; return yPMOS; }
  "posedge"		{ FL; return yPOSEDGE; }
  "primitive"		{ FL; return yPRIMITIVE; }
  "pulldown"		{ FL; return yPULLDOWN; }
  "pullup"		{ FL; return yPULLUP; }
  "rcmos"		{ FL; return yRCMOS; }
  "real"		{ FL; return yREAL; }
  "realtime"		{ FL; return yREALTIME; }
  "reg"			{ FL; return yREG; }
  "repeat"		{ FL; return yREPEAT; }
  "rnmos"		{ FL; return yRNMOS; }
  "rpmos"		{ FL; return yRPMOS; }
  "rtran"		{ FL; return yRTRAN; }
  "rtranif0"		{ FL; return yRTRANIF0; }
  "rtranif1"		{ FL; return yRTRANIF1; }
  "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; }
  "tran"		{ FL; return yTRAN; }
  "tranif0"		{ FL; return yTRANIF0; }
  "tranif1"		{ FL; return yTRANIF1; }
  "tri"			{ FL; return yTRI; }
  "tri0"		{ FL; return yTRI0; }
  "tri1"		{ FL; return yTRI1; }
  "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 */
  "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); }
  "pull0"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "pull1"		{ yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
  "release"		{ 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); }
  "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); }
  "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,VA5,S05,S09,S12,SAX>{
  /*     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,S09,S12,SAX>{
  /*     Keywords */
  "uwire"		{ FL; return yWIRE; }
}

  /* System Verilog 2005 */
<S05,S09,S12,SAX>{
  /*     System Tasks */
  "$bits"		{ FL; return yD_BITS; }
  "$clog2"		{ FL; return yD_CLOG2; }
  "$countones"		{ FL; return yD_COUNTONES; }
  "$dimensions"		{ FL; return yD_DIMENSIONS; }
  "$error"		{ FL; return yD_ERROR; }
  "$fatal"		{ FL; return yD_FATAL; }
  "$high"		{ FL; return yD_HIGH; }
  "$increment"		{ FL; return yD_INCREMENT; }
  "$info"		{ FL; return yD_INFO; }
  "$isunknown"		{ FL; return yD_ISUNKNOWN; }
  "$left"		{ FL; return yD_LEFT; }
  "$low"		{ FL; return yD_LOW; }
  "$onehot"		{ FL; return yD_ONEHOT; }
  "$onehot0"		{ FL; return yD_ONEHOT0; }
  "$right"		{ FL; return yD_RIGHT; }
  "$size"		{ FL; return yD_SIZE; }
  "$unpacked_dimensions" { FL; return yD_UNPACKED_DIMENSIONS; }
  "$warning"		{ FL; return yD_WARNING; }
  /*     SV2005 Keywords */
  "$unit"		{ FL; return yD_UNIT; }  /* Yes, a keyword, not task */
  "always_comb"		{ FL; return yALWAYS_COMB; }
  "always_ff"		{ FL; return yALWAYS_FF; }
  "always_latch"	{ FL; return yALWAYS_LATCH; }
  "assert"		{ FL; return yASSERT; }
  "bind"		{ FL; return yBIND; }
  "bit"			{ FL; return yBIT; }
  "break"		{ FL; return yBREAK; }
  "byte"		{ FL; return yBYTE; }
  "chandle"		{ FL; return yCHANDLE; }
  "clocking"		{ FL; return yCLOCKING; }
  "const"		{ FL; return yCONST__LEX; }
  "context"		{ FL; return yCONTEXT; }
  "continue"		{ FL; return yCONTINUE; }
  "cover"		{ FL; return yCOVER; }
  "do"			{ FL; return yDO; }
  "endclocking"		{ FL; return yENDCLOCKING; }
  "endinterface"	{ FL; return yENDINTERFACE; }
  "endpackage"		{ FL; return yENDPACKAGE; }
  "endprogram"		{ FL; return yENDPROGRAM; }
  "endproperty"		{ FL; return yENDPROPERTY; }
  "enum"		{ FL; return yENUM; }
  "export"		{ FL; return yEXPORT; }
  "final"		{ FL; return yFINAL; }
  "iff"			{ FL; return yIFF; }
  "import"		{ FL; return yIMPORT; }
  "inside"		{ FL; return yINSIDE; }
  "int"			{ FL; return yINT; }
  "interface"		{ FL; return yINTERFACE; }
  "logic"		{ FL; return yLOGIC; }
  "longint"		{ FL; return yLONGINT; }
  "modport"		{ FL; return yMODPORT; }
  "package"		{ FL; return yPACKAGE; }
  "packed"		{ FL; return yPACKED; }
  "priority"		{ FL; return yPRIORITY; }
  "program"		{ FL; return yPROGRAM; }
  "property"		{ FL; return yPROPERTY; }
  "pure"		{ FL; return yPURE; }
  "rand"		{ FL; return yRAND; }
  "randc"		{ FL; return yRANDC; }
  "return"		{ FL; return yRETURN; }
  "shortint"		{ FL; return ySHORTINT; }
  "static"		{ FL; return ySTATIC; }
  "string"		{ FL; return ySTRING; }
  "struct"		{ FL; return ySTRUCT; }
  "timeprecision"	{ FL; return yTIMEPRECISION; }
  "timeunit"		{ FL; return yTIMEUNIT; }
  "type"		{ FL; return yTYPE; }
  "typedef"		{ FL; return yTYPEDEF; }
  "union"		{ FL; return yUNION; }
  "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); }
  "assume"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "before"		{ 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); }
  "class"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "constraint"		{ 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); }
  "endsequence"		{ 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); }
  "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); }
  "new"			{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "null"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
  "protected"		{ 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); }
  "sequence"		{ 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); }
  "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); }
  "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); }
  "within"		{ yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
}

  /* SystemVerilog 2009 */
<S09,S12,SAX>{
  /*     Keywords */
  "global"	 	{ FL; return yGLOBAL__LEX; }
  "unique0"	 	{ FL; return yUNIQUE0; }
  /*     Generic unsupported warnings */
  "accept_on"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "checker"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "endchecker"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "eventually"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "implies"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "let"		 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "nexttime"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "reject_on"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "restrict"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "s_always"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "s_eventually" 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "s_nexttime"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "s_until"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "s_until_with" 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "strong"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "sync_accept_on" 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "sync_reject_on" 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "until"		{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "until_with"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "untyped"	 	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
  "weak"            	{ yyerrorf("Unsupported: SystemVerilog 2009 reserved word not implemented: %s",yytext); }
}

  /* System Verilog 2012 */
<S12,SAX>{
  /*     Keywords */
  "implements"	 	{ yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
  "interconnect" 	{ yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
  "nettype"	 	{ yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
  "soft"	 	{ yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
}

  /* Default PLI rule */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
  "$"[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()->findIdFallback(str)) {
				      FL; return yaD_DPI;
				  } else { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported or unknown PLI call: %s",yytext); }
				}
}

  /************************************************************************/
  /* AMS */

<VA5,SAX>{
  /*     Generic unsupported warnings */
   "above"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "abs"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "absdelay"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "abstol"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "ac_stim"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "access"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "acos"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "acosh"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "aliasparam"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "analog"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "analysis"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "asin"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "asinh"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "assert"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "atan"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "atan2"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "atanh"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "branch"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "ceil"		{ FL; return yD_CEIL; }
   "connect"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "connectmodule"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "connectrules"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "continuous"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "cos"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "cosh"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "cross"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "ddt"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "ddt_nature"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "ddx"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "discipline"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "discrete"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "domain"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "driver_update"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "endconnectrules"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "enddiscipline"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "endnature"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "endparamset"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "exclude"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "exp"		{ FL; return yD_EXP; }
   "final_step"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "flicker_noise"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "floor"		{ FL; return yD_FLOOR; }
   "flow"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "from"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "ground"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "hypot"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "idt"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "idt_nature"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "idtmod"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "inf"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "initial_step"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "laplace_nd"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "laplace_np"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "laplace_zd"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "laplace_zp"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "last_crossing"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "limexp"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "ln"			{ FL; return yD_LN; }
   "log"		{ FL; return yD_LOG10; }
   "max"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "merged"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "min"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "nature"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "net_resolution"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "noise_table"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "paramset"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "potential"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "pow"		{ FL; return yD_POW; }
   "resolveto"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "sin"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "sinh"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "slew"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "split"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "sqrt"		{ FL; return yD_SQRT; }
   "string"		{ FL; return ySTRING; }
   "tan"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "tanh"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "timer"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "transition"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "units"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "white_noise"	{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "wreal"		{ FL; return yWREAL; }
   "zi_nd"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "zi_np"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "zi_zd"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
   "zi_zp"		{ yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
}

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

  /* Converted from //{cmt}verilator ...{cmt} by preprocessor */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
  "/*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_flat_rd*/"	{ FL; return yVL_PUBLIC_FLAT_RD; }
  "/*verilator public_flat_rw*/"	{ FL; return yVL_PUBLIC_FLAT_RW; }  // The @(edge) is converted by the preproc
  "/*verilator public_module*/"		{ FL; return yVL_PUBLIC_MODULE; }
  "/*verilator sc_clock*/"		{ FL; return yVL_CLOCK; }
  "/*verilator clocker*/"		{ FL; return yVL_CLOCKER; }
  "/*verilator no_clocker*/"		{ FL; return yVL_NO_CLOCKER; }
  "/*verilator sc_bv*/"			{ FL; return yVL_SC_BV; }
  "/*verilator sformat*/"		{ FL; return yVL_SFORMAT; }
  "/*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,VA5,S05,S09,S12,SAX>{
  "{"			{ 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]; }
  "|"			{ FL; return yytext[0]; }
  "~"			{ FL; return yytext[0]; }
}

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

  /* Verilog 1995 Operators */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
  "&&"			{ 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,VA5,S05,S09,S12,SAX>{
  "<<<"			{ 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,S09,S12,SAX>{
  "'"			{ 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; }
}

  /* Identifiers and numbers */
<V95,V01,V05,VA5,S05,S09,S12,SAX,VLT>{
  {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(); }

  {vnum}		{
			  /* "# 1'b0" is a delay value so must lex as "#" "1" "'b0" */
			  if (PARSEP->prevLexToken()=='#') {
			      int shortlen = 0;
			      while (isdigit(yytext[shortlen])) shortlen++;
			      if (shortlen) {
				  // Push rest for later parse
				  PARSEP->unputString(yytext+shortlen, yyleng-shortlen);
				  FL; LINECHECKS(yytext,shortlen);
				  // Return is stuff before '
				  yytext[shortlen] = '\0';
				  yylval.nump = PARSEP->newNumber(yylval.fl, (char*)yytext);
				  return yaINTNUM;
			      }
			  }
			  FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
                          return yaINTNUM;
			}
  [0-9][_0-9]*		{
			  FL; yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
                          return yaINTNUM;
			}
  [0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? {
			  FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
                          return yaFLOATNUM;
			}
  [0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) {
			  FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
                          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>{word}		{ yymore(); }
<STRING>.		{ yymore(); }

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

  /************************************************************************/
  /* Attributes */
  /* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
    "(*"({ws}|{crnl})*({id}|{escid})	{ yymore(); yy_push_state(ATTRMODE); }	// Doesn't match (*), but (* attr_spec
}

  /************************************************************************/
  /* Tables */
<TABLE>\\{crnl}		{ yymore(); NEXTLINE(); }
<TABLE>{crnl}		{ NEXTLINE(); yymore(); }
<TABLE>";"		{ FL; 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,VA5,S05,S09,S12,SAX,VLT,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}+"wire"		{ PARSEP->fileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE,true); }
  "`default_nettype"{ws}+"none"		{ PARSEP->fileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE,false); }
  "`default_nettype"{ws}+[a-zA-Z0-9]*	{ yyerrorf("Unsupported: `default_nettype of other than none or wire: %s",yytext); }
  "`default_trireg_strength"{ws}+[^\n\r]*	{ yyerrorf("Unsupported: Verilog optional directive not implemented: %s",yytext); }
  "`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"				{ }
  "`remove_gatenames"			{ } // Verilog-XL compatibility
  "`remove_netnames"			{ } // Verilog-XL compatibility
  "`resetall"				{ PARSEP->fileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE,true); } // Rest handled by preproc
  "`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]*\"VAMS[-0-9.]*\"	{ yy_push_state(VA5); PARSEP->pushBeginKeywords(YY_START); }
  "`begin_keywords"[ \t]*\"1800-2005\"		{ yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); }
  "`begin_keywords"[ \t]*\"1800-2009\"		{ yy_push_state(S09); PARSEP->pushBeginKeywords(YY_START); }
  "`begin_keywords"[ \t]*\"1800-2012\"		{ yy_push_state(S12); PARSEP->pushBeginKeywords(YY_START); }
  "`begin_keywords"[ \t]*\"1800[+]VAMS\"	{ yy_push_state(SAX); PARSEP->pushBeginKeywords(YY_START); } /*Latest SV*/
  "`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; }
  "`verilator_config"			{ BEGIN VLT; }
  "`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,VA5,S05,S09,S12,SAX,VLT>{
  "`"[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; }

double V3ParseImp::parseDouble(const char* textp, size_t length, bool* successp) {
    char* strgp = new char[length+1];
    char* dp=strgp;
    if (successp) *successp = true;
    for (const char* sp=textp; sp<(textp+length); ++sp) {
	if (*sp != '_') *dp++ = *sp;
    }
    *dp++ = '\0';
    char* endp = strgp;
    double d = strtod(strgp, &endp);
    size_t parsed_len = endp-strgp;
    if (parsed_len != strlen(strgp)) {
        if (successp) *successp = false;
        else yyerrorf("Syntax error parsing real: %s",strgp);
    }
    delete[] strgp;
    return d;
}

int V3ParseImp::lexToken() {
    // called from lexToBison, has a "this"
    // Fetch next token from prefetch or real lexer
    int token;
    if (m_ahead) {
	// We prefetched an extra token, give it back
	m_ahead = false;
	token = m_aheadToken;
	yylval = m_aheadVal;
    } else {
	// Parse new token
	token = yylexReadTok();
	//yylval // Set by yylexReadTok()
    }
    // If a paren, read another
    if (token == yCONST__LEX
	|| token == yGLOBAL__LEX
	// Never put yID_* here; below symbol table resolution would break
	) {
	if (debugFlex()) { cout<<"   lexToken: reading ahead to find possible strength"<<endl; }
	V3ParseBisonYYSType curValue = yylval;  // Remember value, as about to read ahead
	int nexttok = yylexReadTok();
	m_ahead = true;
	m_aheadToken = nexttok;
	m_aheadVal = yylval;
	yylval = curValue;
	// Now potentially munge the current token
	if (token == yCONST__LEX) {
	    //UNSUP if (nexttok == yREF) token = yCONST__REF;
	    token = yCONST__ETC;
	}
	else if (token == yGLOBAL__LEX) {
	    if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING;
	    else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); }  // Avoid 2009 "global" conflicting with old code when we can
	}
	// If add to above "else if", also add to "if (token" further above
    }
    // If an id, change the type based on symbol table
    // Note above sometimes converts yGLOBAL to a yaID__LEX
    if (token == yaID__LEX) {
	VSymEnt* foundp;
	if (VSymEnt* look_underp = SYMP->nextId()) {
	    if (debugFlex()) { cout<<"   lexToken: next id lookup forced under "<<look_underp<<endl; }
	    foundp = look_underp->findIdFallback(*(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);
	    foundp = SYMP->symCurrentp()->findIdFallback(*(yylval.strp));
	}
	if (foundp) {
	    AstNode* scp = foundp->nodep();
	    yylval.scp = 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
	    yylval.scp = NULL;
	    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<<"   {"<<yylval.fl->filenameLetters()<<yylval.fl->lineno()
	    <<"} lexToBison  TOKEN="<<tok<<" "<<tokenName(tok);
	if (tok == yaID__ETC || tok == yaID__LEX || tok == yaID__aTYPE) {
	    cout<<"   strp='"<<*(yylval.strp)<<"'";
	}
	cout<<endl;
    }
    return tok;
}

