Commit b3dc3acd by John Kessenich

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).
parent 66e2faf8
......@@ -63,6 +63,7 @@ set(HEADERS
MachineIndependent/ScanContext.h
MachineIndependent/SymbolTable.h
MachineIndependent/Versions.h
MachineIndependent/parseVersions.h
MachineIndependent/preprocessor/PpContext.h
MachineIndependent/preprocessor/PpTokens.h)
......
......@@ -48,14 +48,14 @@ extern int yyparse(glslang::TParseContext*);
namespace glslang {
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb, int v, EProfile p, int spv, int vulkan, EShLanguage L, TInfoSink& is,
bool fc, EShMessages m) :
intermediate(interm), symbolTable(symt), infoSink(is), language(L),
version(v), profile(p), spv(spv), vulkan(vulkan), forwardCompatible(fc),
TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins,
int version, EProfile profile, int spv, int vulkan, EShLanguage language,
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) :
TParseContextBase(symbolTable, interm, version, profile, spv, vulkan, language, infoSink, forwardCompatible, messages),
contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0),
postMainReturn(false),
tokensBeforeEOF(false), limits(resources.limits), messages(m), currentScanner(nullptr),
numErrors(0), parsingBuiltins(pb), afterEOF(false),
inMain(false), postMainReturn(false), currentFunctionType(nullptr), blockName(nullptr),
limits(resources.limits), parsingBuiltins(parsingBuiltins),
afterEOF(false),
atomicUintOffsets(nullptr), anyIndexLimits(false)
{
// ensure we always have a linkage node, even if empty, to simplify tree topology algorithms
......@@ -3133,7 +3133,8 @@ void TParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode *
// Desktop, version 3.30 and later, and ES: "After processing this directive
// (including its new-line), the implementation will behave as if it is compiling at line number line and
// source string number source-string-number.
bool TParseContext::lineDirectiveShouldSetNextLine() const {
bool TParseContext::lineDirectiveShouldSetNextLine() const
{
return profile == EEsProfile || version >= 330;
}
......@@ -5941,32 +5942,4 @@ TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expre
return switchNode;
}
void TParseContext::notifyVersion(int line, int version, const char* type_string)
{
if (versionCallback) {
versionCallback(line, version, type_string);
}
}
void TParseContext::notifyErrorDirective(int line, const char* error_message)
{
if (errorCallback) {
errorCallback(line, error_message);
}
}
void TParseContext::notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
{
if (lineCallback) {
lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
}
}
void TParseContext::notifyExtensionDirective(int line, const char* extension, const char* behavior)
{
if (extensionCallback) {
extensionCallback(line, extension, behavior);
}
}
} // end namespace glslang
......@@ -48,7 +48,7 @@ class TParserToken;
class TScanContext {
public:
explicit TScanContext(TParseContext& pc) : parseContext(pc), afterType(false), field(false) { }
explicit TScanContext(TParseContextBase& pc) : parseContext(pc), afterType(false), field(false) { }
virtual ~TScanContext() { }
static void fillInKeywordMap();
......@@ -72,7 +72,7 @@ protected:
int firstGenerationImage(bool inEs310);
int secondGenerationImage();
TParseContext& parseContext;
TParseContextBase& parseContext;
bool afterType; // true if we've recognized a type, so can only be looking for an identifier
bool field; // true if we're on a field, right after a '.'
TSourceLoc loc;
......
......@@ -464,7 +464,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
// This is the common setup and cleanup code for PreprocessDeferred and
// CompileDeferred.
// It takes any callable with a signature of
// bool (TParseContext& parseContext, TPpContext& ppContext,
// bool (TParseContextBase& parseContext, TPpContext& ppContext,
// TInputScanner& input, bool versionWillBeError,
// TSymbolTable& , TIntermediate& ,
// EShOptimizationLevel , EShMessages );
......@@ -717,7 +717,7 @@ private:
// It places the result in the "string" argument to its constructor.
struct DoPreprocessing {
explicit DoPreprocessing(std::string* string): outputString(string) {}
bool operator()(TParseContext& parseContext, TPpContext& ppContext,
bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
TInputScanner& input, bool versionWillBeError,
TSymbolTable& , TIntermediate& ,
EShOptimizationLevel , EShMessages )
......@@ -828,7 +828,7 @@ struct DoPreprocessing {
// DoFullParse is a valid ProcessingConext template argument for fully
// parsing the shader. It populates the "intermediate" with the AST.
struct DoFullParse{
bool operator()(TParseContext& parseContext, TPpContext& ppContext,
bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
TInputScanner& fullInput, bool versionWillBeError,
TSymbolTable& symbolTable, TIntermediate& intermediate,
EShOptimizationLevel optLevel, EShMessages messages)
......@@ -837,13 +837,13 @@ struct DoFullParse{
// Parse the full shader.
if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError))
success = false;
intermediate.addSymbolLinkageNodes(parseContext.linkage, parseContext.language, symbolTable);
intermediate.addSymbolLinkageNodes(parseContext.getLinkage(), parseContext.getLanguage(), symbolTable);
if (success && intermediate.getTreeRoot()) {
if (optLevel == EShOptNoGeneration)
parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested.");
else
success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.language);
success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.getLanguage());
} else if (! success) {
parseContext.infoSink.info.prefix(EPrefixError);
parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
......
//
//Copyright (C) 2016 Google, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
// This is implemented in Versions.cpp
#ifndef _PARSE_VERSIONS_INCLUDED_
#define _PARSE_VERSIONS_INCLUDED_
#include "../Public/ShaderLang.h"
#include "../Include/InfoSink.h"
#include "Scan.h"
#include <map>
namespace glslang {
//
// Base class for parse helpers.
// This just has version-related information and checking.
// This class should be sufficient for preprocessing.
//
class TParseVersions {
public:
TParseVersions(TIntermediate& interm, int version, EProfile profile,
int spv, int vulkan, EShLanguage language, TInfoSink& infoSink,
bool forwardCompatible, EShMessages messages)
: infoSink(infoSink), version(version), profile(profile), language(language),
spv(spv), vulkan(vulkan), forwardCompatible(forwardCompatible),
intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { }
virtual ~TParseVersions() { }
virtual void initializeExtensionBehavior();
virtual void requireProfile(const TSourceLoc&, int queryProfiles, const char* featureDesc);
virtual void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, const char* const extension, const char* featureDesc);
virtual void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc);
virtual void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc);
virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc);
virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc);
virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual TExtensionBehavior getExtensionBehavior(const char*);
virtual bool extensionTurnedOn(const char* const extension);
virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]);
virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
virtual void doubleCheck(const TSourceLoc&, const char* op);
virtual void spvRemoved(const TSourceLoc&, const char* op);
virtual void vulkanRemoved(const TSourceLoc&, const char* op);
virtual void requireVulkan(const TSourceLoc&, const char* op);
virtual void requireSpv(const TSourceLoc&, const char* op);
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...) = 0;
virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...) = 0;
virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...) = 0;
virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...) = 0;
void addError() { ++numErrors; }
int getNumErrors() const { return numErrors; }
void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
TInputScanner* getScanner() const { return currentScanner; }
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); }
const char* getPreamble();
bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; }
bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
TInfoSink& infoSink;
// compilation mode
int version; // version, updated by #version in the shader
EProfile profile; // the declared profile in the shader (core by default)
EShLanguage language; // really the stage
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
TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
protected:
EShMessages messages; // errors/warnings/rule-sets
int numErrors; // number of compile-time errors encountered
TInputScanner* currentScanner;
private:
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
explicit TParseVersions(const TParseVersions&);
TParseVersions& operator=(const TParseVersions&);
};
} // end namespace glslang
#endif // _PARSE_VERSIONS_INCLUDED_
......@@ -83,7 +83,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace glslang {
TPpContext::TPpContext(TParseContext& pc, const TShader::Includer& inclr) :
TPpContext::TPpContext(TParseContextBase& pc, const TShader::Includer& inclr) :
preamble(0), strings(0), parseContext(pc), includer(inclr), inComment(false)
{
InitAtomTable();
......
......@@ -121,7 +121,7 @@ class TInputScanner;
// Don't expect too much in terms of OO design.
class TPpContext {
public:
TPpContext(TParseContext&, const TShader::Includer&);
TPpContext(TParseContextBase&, const TShader::Includer&);
virtual ~TPpContext();
void setPreamble(const char* preamble, size_t length);
......@@ -213,7 +213,7 @@ protected:
// Scanner data:
int previous_token;
TParseContext& parseContext;
TParseContextBase& parseContext;
// Get the next token from *stack* of input sources, popping input sources
// that are out of tokens, down until an input sources is found that has a token.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment