mirror of
https://github.com/verilator/verilator.git
synced 2025-02-08 06:32:24 +00:00
This requires the parse symbol table persist across all parse runs. This is probably more correct than before, but may result in some fallout if people relied on data types not being persistant across separately parsed cells.
228 lines
7.5 KiB
C++
228 lines
7.5 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||
//*************************************************************************
|
||
// DESCRIPTION: Verilator: Common header between parser and lex
|
||
//
|
||
// Code available from: http://www.veripool.org/verilator
|
||
//
|
||
//*************************************************************************
|
||
//
|
||
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
|
||
// redistribute it and/or modify it under the terms of either the GNU
|
||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||
// Version 2.0.
|
||
//
|
||
// Verilator is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// GNU General Public License for more details.
|
||
//
|
||
//*************************************************************************
|
||
|
||
#ifndef _V3PARSEIMP_H_
|
||
#define _V3PARSEIMP_H_ 1
|
||
#include "config_build.h"
|
||
#include "verilatedos.h"
|
||
#include "V3Error.h"
|
||
#include "V3Global.h"
|
||
#include "V3Parse.h"
|
||
#include "V3ParseSym.h"
|
||
#include <deque>
|
||
|
||
class V3Lexer;
|
||
|
||
// IMPORTANT: Don't include this file other than in the bison and flex,
|
||
// as it's definitions will confuse other parsers
|
||
|
||
//======================================================================
|
||
// Types (between parser & lexer)
|
||
|
||
typedef enum { uniq_NONE, uniq_UNIQUE, uniq_UNIQUE0, uniq_PRIORITY } V3UniqState;
|
||
|
||
typedef enum { iprop_NONE, iprop_CONTEXT, iprop_PURE } V3ImportProperty;
|
||
|
||
//============================================================================
|
||
// We can't use bison's %union as we want to pass the fileline with all tokens
|
||
|
||
struct V3ParseBisonYYSType {
|
||
FileLine* fl;
|
||
AstNode* scp; // Symbol table scope for future lookups
|
||
union {
|
||
V3Number* nump;
|
||
string* strp;
|
||
int cint;
|
||
double cdouble;
|
||
bool cbool;
|
||
V3UniqState uniqstate;
|
||
VSignedState signstate;
|
||
V3ImportProperty iprop;
|
||
V3ErrorCode::en errcodeen;
|
||
|
||
AstNode* nodep;
|
||
|
||
AstBasicDType* bdtypep;
|
||
AstBegin* beginp;
|
||
AstCase* casep;
|
||
AstCaseItem* caseitemp;
|
||
AstCell* cellp;
|
||
AstConst* constp;
|
||
AstMemberDType* memberp;
|
||
AstNodeModule* modulep;
|
||
AstNodeClassDType* classp;
|
||
AstNodeDType* dtypep;
|
||
AstNodeFTask* ftaskp;
|
||
AstNodeFTaskRef* ftaskrefp;
|
||
AstNodeSenItem* senitemp;
|
||
AstNodeVarRef* varnodep;
|
||
AstPackage* packagep;
|
||
AstParseRef* parserefp;
|
||
AstPatMember* patmemberp;
|
||
AstPin* pinp;
|
||
AstRange* rangep;
|
||
AstSenTree* sentreep;
|
||
AstVar* varp;
|
||
AstVarRef* varrefp;
|
||
};
|
||
};
|
||
|
||
#define YYSTYPE V3ParseBisonYYSType
|
||
|
||
//######################################################################
|
||
|
||
class V3ParseImp {
|
||
// MEMBERS
|
||
AstNetlist* m_rootp; // Root of the design
|
||
V3InFilter* m_filterp; // Reading filter
|
||
V3ParseSym* m_symp; // Symbol table
|
||
|
||
V3Lexer* m_lexerp; // Current FlexLexer
|
||
static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based
|
||
FileLine* m_fileline; // Filename/linenumber currently active
|
||
|
||
bool m_inCellDefine; // Inside a `celldefine
|
||
bool m_inLibrary; // Currently reading a library vs. regular file
|
||
int m_inBeginKwd; // Inside a `begin_keywords
|
||
int m_lastVerilogState; // Last LEX state in `begin_keywords
|
||
|
||
bool m_ahead; // aheadToken is valid
|
||
int m_aheadToken; // Token we read ahead
|
||
V3ParseBisonYYSType m_aheadVal; // aheadToken's value
|
||
|
||
deque<string*> m_stringps; // Created strings for later cleanup
|
||
deque<V3Number*> m_numberps; // Created numbers for later cleanup
|
||
deque<FileLine> m_lintState; // Current lint state for save/restore
|
||
deque<string> m_ppBuffers; // Preprocessor->lex buffer of characters to process
|
||
|
||
public:
|
||
// Note these are an exception to using the filename as the debug type
|
||
static int debugBison() {
|
||
static int level = -1;
|
||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("bison");
|
||
return level;
|
||
}
|
||
static int debugFlex() {
|
||
static int level = -1;
|
||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("flex");
|
||
return level;
|
||
}
|
||
static int debug() { return debugBison() ? debugFlex() : 0; }
|
||
|
||
// Functions called by lex rules:
|
||
int yylexThis();
|
||
static bool optPsl() { return v3Global.opt.psl(); }
|
||
static bool optFuture(const string& flag) { return v3Global.opt.isFuture(flag); }
|
||
|
||
void ppline (const char* text);
|
||
void linenoInc() { fileline()->linenoInc(); }
|
||
void verilatorCmtLint(const char* text, bool on);
|
||
void verilatorCmtLintSave();
|
||
void verilatorCmtLintRestore();
|
||
void verilatorCmtBad(const char* text);
|
||
double parseDouble(const char* text, size_t length);
|
||
void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; }
|
||
bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; }
|
||
int lastVerilogState() const { return m_lastVerilogState; }
|
||
static const char* tokenName(int tok);
|
||
|
||
void ppPushText(const string& text) { m_ppBuffers.push_back(text); }
|
||
size_t ppInputToLex(char* buf, size_t max_size);
|
||
|
||
static V3ParseImp* parsep() { return s_parsep; }
|
||
|
||
// TODO: Many of these functions are the old interface; they'd be better as non-static
|
||
// and called as READP->newString(...) etc.
|
||
string* newString(const string& text) {
|
||
// Allocate a string, remembering it so we can reclaim storage at lex end
|
||
string* strp = new string (text);
|
||
m_stringps.push_back(strp);
|
||
return strp;
|
||
}
|
||
string* newString(const char* text) {
|
||
// Allocate a string, remembering it so we can reclaim storage at lex end
|
||
string* strp = new string (text);
|
||
m_stringps.push_back(strp);
|
||
return strp;
|
||
}
|
||
string* newString(const char* text, size_t length) {
|
||
string* strp = new string (text, length);
|
||
m_stringps.push_back(strp);
|
||
return strp;
|
||
}
|
||
V3Number* newNumber(FileLine* fl, const char* text) {
|
||
V3Number* nump = new V3Number (fl, text);
|
||
m_numberps.push_back(nump);
|
||
return nump;
|
||
}
|
||
|
||
// Return next token, for bison, since bison isn't class based, use a global THIS
|
||
FileLine* fileline() const { return m_fileline; }
|
||
AstNetlist* rootp() const { return m_rootp; }
|
||
FileLine* copyOrSameFileLine() { return fileline()->copyOrSameFileLine(); }
|
||
bool inCellDefine() const { return m_inCellDefine; }
|
||
void inCellDefine(bool flag) { m_inCellDefine = flag; }
|
||
bool inLibrary() const { return m_inLibrary; }
|
||
|
||
// Interactions with parser
|
||
int bisonParse();
|
||
|
||
// Interactions with lexer
|
||
void lexNew(int debug);
|
||
void lexDestroy();
|
||
void stateExitPsl(); // Parser -> lexer communication
|
||
void statePushVlg(); // Parser -> lexer communication
|
||
void statePop(); // Parser -> lexer communication
|
||
static int stateVerilogRecent(); // Parser -> lexer communication
|
||
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); }
|
||
|
||
//==== Symbol tables
|
||
V3ParseSym* symp() { return m_symp; }
|
||
|
||
public:
|
||
// CREATORS
|
||
V3ParseImp(AstNetlist* rootp, V3InFilter* filterp, V3ParseSym* parserSymp)
|
||
: m_rootp(rootp), m_filterp(filterp), m_symp(parserSymp) {
|
||
m_fileline = NULL;
|
||
m_lexerp = NULL;
|
||
m_inCellDefine = false;
|
||
m_inLibrary = false;
|
||
m_inBeginKwd = 0;
|
||
m_lastVerilogState = stateVerilogRecent();
|
||
m_ahead = false;
|
||
m_aheadToken = 0;
|
||
}
|
||
~V3ParseImp();
|
||
void parserClear();
|
||
|
||
// METHODS
|
||
// Preprocess and read the Verilog file specified into the netlist database
|
||
int lexToBison(); // Pass token to bison
|
||
|
||
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
|
||
const string& errmsg);
|
||
|
||
private:
|
||
void lexFile(const string& modname);
|
||
int lexToken(); // Internal; called from lexToBison
|
||
};
|
||
|
||
#endif // Guard
|