Refactor TParseContext into 3 level inheritance.

Adds parseVersions.h as the base TParseVersions for versioning,
and splits the remainder between TParseContextBase (sharable across parsers)
and TParseContext (now the GLSL-specific part).
This commit is contained in:
John Kessenich 2016-03-12 19:08:55 -07:00
parent 66e2faf844
commit b3dc3acd59
9 changed files with 272 additions and 159 deletions

View file

@ -33,10 +33,18 @@
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
//
// This header defines a two-level parse-helper hierarchy, derived from
// TParseVersions:
// - TParseContextBase: sharable across multiple parsers
// - TParseContext: GLSL specific helper
//
#ifndef _PARSER_HELPER_INCLUDED_
#define _PARSER_HELPER_INCLUDED_
#include "Versions.h"
#include "parseVersions.h"
#include "../Include/ShHandle.h"
#include "SymbolTable.h"
#include "localintermediate.h"
@ -60,10 +68,88 @@ class TPpContext;
typedef std::set<int> TIdSetType;
//
// The following are extra variables needed during parsing, grouped together so
// they can be passed to the parser without needing a global.
// Sharable code (as well as what's in TParseVersions) across
// parse helpers.
//
class TParseContext {
class TParseContextBase : public TParseVersions {
public:
TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, int version,
EProfile profile, int spv, int vulkan, EShLanguage language,
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages)
: TParseVersions(interm, version, profile, spv, vulkan, language, infoSink, forwardCompatible, messages),
symbolTable(symbolTable), tokensBeforeEOF(false),
linkage(nullptr), scanContext(nullptr), ppContext(nullptr) { }
virtual ~TParseContextBase() { }
virtual void setLimits(const TBuiltInResource&) = 0;
EShLanguage getLanguage() const { return language; }
TIntermAggregate*& getLinkage() { return linkage; }
void setScanContext(TScanContext* c) { scanContext = c; }
TScanContext* getScanContext() const { return scanContext; }
void setPpContext(TPpContext* c) { ppContext = c; }
TPpContext* getPpContext() const { return ppContext; }
virtual void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
virtual void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0;
virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0;
virtual bool lineDirectiveShouldSetNextLine() const = 0;
virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0;
virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0;
virtual void notifyVersion(int line, int version, const char* type_string)
{
if (versionCallback)
versionCallback(line, version, type_string);
}
virtual void notifyErrorDirective(int line, const char* error_message)
{
if (errorCallback)
errorCallback(line, error_message);
}
virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
{
if (lineCallback)
lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
}
virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior)
{
if (extensionCallback)
extensionCallback(line, extension, behavior);
}
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
bool tokensBeforeEOF;
protected:
TParseContextBase(TParseContextBase&);
TParseContextBase& operator=(TParseContextBase&);
TIntermAggregate* linkage; // aggregate node of objects the linker may need, if not referenced by the rest of the AST
TScanContext* scanContext;
TPpContext* ppContext;
// These, if set, will be called when a line, pragma ... is preprocessed.
// They will be called with any parameters to the original directive.
std::function<void(int, int, bool, int, const char*)> lineCallback;
std::function<void(int, const TVector<TString>&)> pragmaCallback;
std::function<void(int, int, const char*)> versionCallback;
std::function<void(int, const char*, const char*)> extensionCallback;
std::function<void(int, const char*)> errorCallback;
};
//
// GLSL-specific parse helper. Should have GLSL in the name, but that's
// too big of a change for comparing branches at the moment, and perhaps
// impacts downstream consumers as well.
//
class TParseContext : public TParseContextBase {
public:
TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, int spv, int vulkan, EShLanguage, TInfoSink&,
bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
@ -72,7 +158,6 @@ public:
void setLimits(const TBuiltInResource&);
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false);
void parserError(const char* s); // for bison's yyerror
const char* getPreamble();
void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...);
@ -83,12 +168,10 @@ public:
void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...);
bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; }
bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
void reservedErrorCheck(const TSourceLoc&, const TString&);
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op);
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment);
bool lineDirectiveShouldSetNextLine() const;
bool builtInName(const TString&);
void handlePragma(const TSourceLoc&, const TVector<TString>&);
@ -210,55 +293,6 @@ public:
void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
void setScanContext(TScanContext* c) { scanContext = c; }
TScanContext* getScanContext() const { return scanContext; }
void setPpContext(TPpContext* c) { ppContext = c; }
TPpContext* getPpContext() const { return ppContext; }
void addError() { ++numErrors; }
int getNumErrors() const { return numErrors; }
const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); }
void setCurrentLine(int line) { currentScanner->setLine(line); }
void setCurrentColumn(int col) { currentScanner->setColumn(col); }
void setCurrentSourceName(const char* name) { currentScanner->setFile(name); }
void setCurrentString(int string) { currentScanner->setString(string); }
void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
TInputScanner* getScanner() const { return currentScanner; }
bool lineDirectiveShouldSetNextLine() const;
void notifyVersion(int line, int version, const char* type_string);
void notifyErrorDirective(int line, const char* error_message);
void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName);
void notifyExtensionDirective(int line, const char* extension, const char* behavior);
// The following are implemented in Versions.cpp to localize version/profile/stage/extensions control
void initializeExtensionBehavior();
void requireProfile(const TSourceLoc&, int queryProfiles, const char* featureDesc);
void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc);
void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, const char* const extension, const char* featureDesc);
void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc);
void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc);
void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc);
void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc);
void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
TExtensionBehavior getExtensionBehavior(const char*);
bool extensionTurnedOn(const char* const extension);
bool extensionsTurnedOn(int numExtensions, const char* const extensions[]);
void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
void fullIntegerCheck(const TSourceLoc&, const char* op);
void doubleCheck(const TSourceLoc&, const char* op);
void spvRemoved(const TSourceLoc&, const char* op);
void vulkanRemoved(const TSourceLoc&, const char* op);
void requireVulkan(const TSourceLoc&, const char* op);
void requireSpv(const TSourceLoc&, const char* op);
void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
protected:
void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
void inheritGlobalDefaults(TQualifier& dst) const;
@ -268,8 +302,6 @@ protected:
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
TOperator mapTypeToConstructorOp(const TType&) const;
bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
void finalErrorCheck();
void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, TPrefixType prefix,
@ -280,18 +312,6 @@ public:
// Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
//
TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
TInfoSink& infoSink;
// compilation mode
EShLanguage language; // vertex or fragment language
int version; // version, updated by #version in the shader
EProfile profile; // the declared profile in the shader (core by default)
int spv; // SPIR-V version; 0 means not SPIR-V
int vulkan; // Vulkan version; 0 means not vulkan
bool forwardCompatible; // true if errors are to be given for use of deprecated features
// Current state of parsing
struct TPragma contextPragma;
int loopNestingLevel; // 0 if outside all loops
@ -306,9 +326,7 @@ public:
bool functionReturnsValue; // true if a non-void function has a return
const TString* blockName;
TQualifier currentBlockQualifier;
TIntermAggregate *linkage; // aggregate node of objects the linker may need, if not referenced by the rest of the AST
TPrecisionQualifier defaultPrecision[EbtNumTypes];
bool tokensBeforeEOF;
TBuiltInResource resources;
TLimits& limits;
@ -316,13 +334,7 @@ protected:
TParseContext(TParseContext&);
TParseContext& operator=(TParseContext&);
EShMessages messages; // errors/warnings/rule-sets
TScanContext* scanContext;
TPpContext* ppContext;
TInputScanner* currentScanner;
int numErrors; // number of compile-time errors encountered
bool parsingBuiltins; // true if parsing built-in symbols/functions
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2)); // see computeSamplerTypeIndex()
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
bool afterEOF;
@ -369,14 +381,6 @@ protected:
// array-sizing declarations
//
TVector<TSymbol*> ioArraySymbolResizeList;
// These, if set, will be called when a line, pragma ... is preprocessed.
// They will be called with any parameters to the original directive.
std::function<void(int, int, bool, int, const char*)> lineCallback;
std::function<void(int, const TVector<TString>&)> pragmaCallback;
std::function<void(int, int, const char*)> versionCallback;
std::function<void(int, const char*, const char*)> extensionCallback;
std::function<void(int, const char*)> errorCallback;
};
} // end namespace glslang