#include "localintermediate.h"
#include "QualifierAlive.h"
#include "RemoveTree.h"
+#include "SymbolTable.h"
+
#include <float.h>
namespace glslang {
//
// This deletes the tree.
//
-void TIntermediate::remove(TIntermNode* root)
+void TIntermediate::removeTree()
{
- if (root)
- RemoveAllTreeNodes(root);
+ if (treeRoot)
+ RemoveAllTreeNodes(treeRoot);
}
////////////////////////////////////////////////////////////////
case EbtDouble:
leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst()));
break;
- default:
+ default:
return node;
}
break;
//
#include "ParseHelper.h"
+
#include "osinclude.h"
#include <stdarg.h>
#include <algorithm>
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb, int v, EProfile p, EShLanguage L, TInfoSink& is,
bool fc, EShMessages m) :
- intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0), linkage(0),
- numErrors(0), loopNestingLevel(0),
- structNestingLevel(0), inTypeParen(false), parsingBuiltins(pb),
- version(v), profile(p), forwardCompatible(fc), messages(m),
- contextPragma(true, false), afterEOF(false), tokensBeforeEOF(false)
+ intermediate(interm), symbolTable(symt), infoSink(is), language(L),
+ version(v), profile(p), forwardCompatible(fc), messages(m),
+ contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0),
+ linkage(0), tokensBeforeEOF(false),
+ parsingBuiltins(pb), numErrors(0), afterEOF(false)
{
currentLoc.line = 1;
currentLoc.string = 0;
TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, EShLanguage, TInfoSink&,
bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
- TScanContext* scanContext;
- TPpContext* ppContext;
- TIntermediate& intermediate; // to hold and build a parse tree
- TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
- TInfoSink& infoSink;
- EShLanguage language; // vertex or fragment language
- TIntermNode* treeRoot; // root of parse tree being created
- TIntermAggregate *linkage; // aggregate node of objects the linker may need, if not reference by the rest of the AST
- int numErrors; // number of compile-time errors encountered
- int loopNestingLevel; // 0 if outside all loops
- int structNestingLevel; // 0 if outside blocks and structures
- TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
- bool inTypeParen; // true if in parentheses, looking only for an identifier
- const TType* currentFunctionType; // the return type of the function that's currently being parsed
- bool functionReturnsValue; // true if a non-void function has a return
- bool parsingBuiltins; // true if parsing built-in symbols/functions
-
- int version; // version, updated by #version in the shader
- EProfile profile; // the declared profile in the shader (core by default)
- bool forwardCompatible; // true if errors are to be given for use of deprecated features
- EShMessages messages; // errors/warnings
- TMap<TString, TBehavior> extensionBehavior; // for each extension string, what it's current enablement is
-
- struct TPragma contextPragma;
- TPrecisionQualifier defaultPrecision[EbtNumTypes];
- static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2)); // see computeSamplerTypeIndex()
- TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
- bool afterEOF;
- bool tokensBeforeEOF;
- TSourceLoc currentLoc;
- const TString* blockName;
- TQualifier globalUniformDefaults;
- TQualifier globalInputDefaults;
- TQualifier globalOutputDefaults;
- TQualifier currentBlockDefaults;
-
- void initializeExtensionBehavior();
- const char* getPreamble();
+public:
bool parseShaderStrings(TPpContext&, char* strings[], int strLen[], int numStrings);
- void parserError(const char *s);
+ void initializeExtensionBehavior();
+ void parserError(const char *s); // for bison's yyerror
- void handlePragma(const char **tokens, int numTokens);
- TBehavior getExtensionBehavior(const char* behavior);
- void updateExtensionBehavior(const char* extName, const char* behavior);
-
void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...);
void C_DECL warn(TSourceLoc, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...);
bool reservedErrorCheck(TSourceLoc, const TString& identifier);
+ void updateExtensionBehavior(const char* extName, const char* behavior);
+ void handlePragma(const char **tokens, int numTokens);
TIntermTyped* handleVariable(TSourceLoc, TSymbol* symbol, TString* string);
TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
void requireNotRemoved(TSourceLoc, EProfile callingProfile, int removedVersion, const char *featureDesc);
void fullIntegerCheck(TSourceLoc, const char* op);
void doubleCheck(TSourceLoc, const char* op);
+
+ void setScanContext(TScanContext* c) { scanContext = c; }
+ TScanContext* getScanContext() const { return scanContext; }
+ void setPpContext(TPpContext* c) { ppContext = c; }
+ TPpContext* getPpContext() const { return ppContext; }
+ int getNumErrors() const { return numErrors; }
+
+protected:
+ const char* getPreamble();
+ TBehavior getExtensionBehavior(const char* behavior);
+
+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)
+ bool forwardCompatible; // true if errors are to be given for use of deprecated features
+ EShMessages messages; // errors/warnings
+
+ // Current state of parsing
+ struct TPragma contextPragma;
+ int loopNestingLevel; // 0 if outside all loops
+ int structNestingLevel; // 0 if outside blocks and structures
+ TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
+ const TType* currentFunctionType; // the return type of the function that's currently being parsed
+ bool functionReturnsValue; // true if a non-void function has a return
+ const TString* blockName;
+ TQualifier currentBlockDefaults;
+ TIntermAggregate *linkage; // aggregate node of objects the linker may need, if not referenced by the rest of the AST
+ TPrecisionQualifier defaultPrecision[EbtNumTypes];
+ TSourceLoc currentLoc;
+ bool tokensBeforeEOF;
+
+protected:
+ TScanContext* scanContext;
+ TPpContext* ppContext;
+ int numErrors; // number of compile-time errors encountered
+ bool parsingBuiltins; // true if parsing built-in symbols/functions
+ TMap<TString, TBehavior> extensionBehavior; // for each extension string, what it's current enablement is
+ static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2)); // see computeSamplerTypeIndex()
+ TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
+ bool afterEOF;
+ TQualifier globalUniformDefaults;
+ TQualifier globalInputDefaults;
+ TQualifier globalOutputDefaults;
};
} // end namespace glslang
{
glslang::TParserToken token(*glslangTokenDesc);
- return parseContext.scanContext->tokenize(parseContext.ppContext, token);
+ return parseContext.getScanContext()->tokenize(parseContext.getPpContext(), token);
}
namespace {
TParseContext parseContext(symbolTable, intermediate, true, version, profile, language, infoSink);
TPpContext ppContext(parseContext);
TScanContext scanContext(parseContext);
- parseContext.scanContext = &scanContext;
- parseContext.ppContext = &ppContext;
+ parseContext.setScanContext(&scanContext);
+ parseContext.setPpContext(&ppContext);
//
// Parse the built-ins. This should only happen once per
// Do an actual compile on the given strings. The result is left
// in the given compile object.
//
-// Return: The return value of ShCompile is really boolean, indicating
-// success or failure.
+// Return: The return value is really boolean, indicating
+// success (1) or failure (0).
//
int ShCompile(
const ShHandle handle,
TParseContext parseContext(symbolTable, intermediate, false, version, profile, compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
glslang::TScanContext scanContext(parseContext);
TPpContext ppContext(parseContext);
- parseContext.scanContext = &scanContext;
- parseContext.ppContext = &ppContext;
+ parseContext.setScanContext(&scanContext);
+ parseContext.setPpContext(&ppContext);
TSourceLoc beginning;
beginning.line = 1;
bool ret = parseContext.parseShaderStrings(ppContext, const_cast<char**>(shaderStrings), lengths, numStrings);
if (! ret)
success = false;
- intermediate.addSymbolLinkageNodes(parseContext.treeRoot, parseContext.linkage, parseContext.language, symbolTable);
+ intermediate.addSymbolLinkageNodes(intermediate.getTreeRoot(), parseContext.linkage, parseContext.language, symbolTable);
// Clean up the symbol table before deallocating the pool memory it used.
// The AST is self-sufficient now, so it can be done before the rest of compilation/linking.
delete symbolTableMemory;
- if (success && parseContext.treeRoot) {
+ 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(parseContext.treeRoot, parseContext.language);
+ success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.language);
if (success) {
- if (messages & EShMsgAST)
- intermediate.outputTree(parseContext.treeRoot, parseContext.infoSink);
-
//
// Call the machine dependent compiler
//
- if (! compiler->compile(parseContext.treeRoot, parseContext.version, parseContext.profile))
+ if (! compiler->compile(intermediate.getTreeRoot(), parseContext.version, parseContext.profile))
success = false;
}
}
} else if (! success) {
parseContext.infoSink.info.prefix(EPrefixError);
- parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n";
+ parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
success = false;
- if (messages & EShMsgAST)
- intermediate.outputTree(parseContext.treeRoot, parseContext.infoSink);
}
- intermediate.remove(parseContext.treeRoot);
+ if (messages & EShMsgAST)
+ intermediate.outputTree(parseContext.infoSink);
+
+ intermediate.removeTree();
//
// Throw away all the temporary memory used by the compilation process.
//
translation_unit\r
: external_declaration {\r
$$ = $1;\r
- parseContext.treeRoot = $$;\r
+ parseContext.intermediate.setTreeRoot($$);\r
}\r
| translation_unit external_declaration {\r
$$ = parseContext.intermediate.growAggregate($1, $2);\r
- parseContext.treeRoot = $$;\r
+ parseContext.intermediate.setTreeRoot($$);\r
}\r
;\r
\r
//
#include "localintermediate.h"
+#include "../Include/InfoSink.h"
namespace glslang {
// Individual functions can be initialized to 0 to skip processing of that
// type of node. It's children will still be processed.
//
-void TIntermediate::outputTree(TIntermNode* root, TInfoSink& infoSink)
+void TIntermediate::outputTree(TInfoSink& infoSink)
{
- if (root == 0)
+ if (treeRoot == 0)
return;
TOutputTraverser it(infoSink);
it.visitBranch = OutputBranch;
it.visitSwitch = OutputSwitch;
- root->traverse(&it);
+ treeRoot->traverse(&it);
}
} // end namespace glslang
#include "../Include/intermediate.h"
#include "../Public/ShaderLang.h"
-#include "SymbolTable.h"
#include "Versions.h"
+class TInfoSink;
+
namespace glslang {
struct TVectorFields {
int num;
};
+class TSymbolTable;
+class TVariable;
+
//
// Set of helper functions to help parse and build the tree.
//
class TIntermediate {
-public:
- POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
+public:
+ TIntermediate(int v, EProfile p) : treeRoot(0), profile(p), version(v) { }
- TIntermediate(int v, EProfile p) : version(v), profile(p) { }
+ void setTreeRoot(TIntermNode* r) { treeRoot = r; }
+ TIntermNode* getTreeRoot() const { return treeRoot; }
+
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
void addSymbolLinkageNodes(TIntermNode* root, TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
void addSymbolLinkageNode(TIntermAggregate*& linkage, const TVariable&);
- void remove(TIntermNode*);
- void outputTree(TIntermNode*, TInfoSink&);
-
+
+ void outputTree(TInfoSink& infoSink);
+ void removeTree();
+
protected:
+ TIntermNode* treeRoot;
EProfile profile;
int version;