mirror of
https://github.com/KhronosGroup/glslang
synced 2024-09-20 04:40:01 +00:00
HLSL: Grammar: Generalize accepting a declaration to accept an aggregate of subtrees.
This is slightly cleaner today for entry-point wrapping, which sometimes made two subtrees for a function definition instead of just one subtree. It will be critical though for recognizing a struct with multiple member functions.
This commit is contained in:
parent
057df2935a
commit
ca71d946d7
@ -2,5 +2,5 @@
|
||||
// For the version, it uses the latest git tag followed by the number of commits.
|
||||
// For the date, it uses the current date (when then script is run).
|
||||
|
||||
#define GLSLANG_REVISION "Overload400-PrecQual.1881"
|
||||
#define GLSLANG_DATE "06-Mar-2017"
|
||||
#define GLSLANG_REVISION "Overload400-PrecQual.1882"
|
||||
#define GLSLANG_DATE "07-Mar-2017"
|
||||
|
@ -1158,15 +1158,15 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
|
||||
return nullptr;
|
||||
|
||||
TIntermAggregate* aggNode = nullptr;
|
||||
if (left)
|
||||
if (left != nullptr)
|
||||
aggNode = left->getAsAggregate();
|
||||
if (! aggNode || aggNode->getOp() != EOpNull) {
|
||||
if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
|
||||
aggNode = new TIntermAggregate;
|
||||
if (left)
|
||||
if (left != nullptr)
|
||||
aggNode->getSequence().push_back(left);
|
||||
}
|
||||
|
||||
if (right)
|
||||
if (right != nullptr)
|
||||
aggNode->getSequence().push_back(right);
|
||||
|
||||
return aggNode;
|
||||
|
@ -131,18 +131,13 @@ bool HlslGrammar::acceptCompilationUnit()
|
||||
continue;
|
||||
|
||||
// externalDeclaration
|
||||
TIntermNode* declarationNode1;
|
||||
TIntermNode* declarationNode2 = nullptr; // sometimes the grammar for a single declaration creates two
|
||||
if (! acceptDeclaration(declarationNode1, declarationNode2))
|
||||
if (! acceptDeclaration(unitNode))
|
||||
return false;
|
||||
|
||||
// hook it up
|
||||
unitNode = intermediate.growAggregate(unitNode, declarationNode1);
|
||||
if (declarationNode2 != nullptr)
|
||||
unitNode = intermediate.growAggregate(unitNode, declarationNode2);
|
||||
}
|
||||
|
||||
// set root of AST
|
||||
if (unitNode && !unitNode->getAsAggregate())
|
||||
unitNode = intermediate.growAggregate(nullptr, unitNode);
|
||||
intermediate.setTreeRoot(unitNode);
|
||||
|
||||
return true;
|
||||
@ -292,21 +287,17 @@ bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
|
||||
// as above. (The 'identifier' in the first item in init_declarator list is the
|
||||
// same as 'identifier' for function declarations.)
|
||||
//
|
||||
// 'node' could get populated if the declaration creates code, like an initializer
|
||||
// or a function body.
|
||||
// This can generate more than one subtree, one per initializer or a function body.
|
||||
// All initializer subtrees are put in their own aggregate node, making one top-level
|
||||
// node for all the initializers. Each function created is a top-level node to grow
|
||||
// into the passed-in nodeList.
|
||||
//
|
||||
// 'node2' could get populated with a second decoration tree if a single source declaration
|
||||
// leads to two subtrees that need to be peers higher up.
|
||||
// If 'nodeList' is passed in as non-null, it must an aggregate to extend for
|
||||
// each top-level node the declaration creates. Otherwise, if only one top-level
|
||||
// node in generated here, that is want is returned in nodeList.
|
||||
//
|
||||
bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
|
||||
bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
|
||||
{
|
||||
TIntermNode* node2;
|
||||
return acceptDeclaration(node, node2);
|
||||
}
|
||||
bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
||||
{
|
||||
node = nullptr;
|
||||
node2 = nullptr;
|
||||
bool list = false;
|
||||
|
||||
// attributes
|
||||
@ -324,9 +315,8 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
||||
// HLSL shaders, this will have to be a master level switch
|
||||
// As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
|
||||
// For that reason, this line is commented out
|
||||
|
||||
// if (acceptSamplerDeclarationDX9(declaredType))
|
||||
// return true;
|
||||
// if (acceptSamplerDeclarationDX9(declaredType))
|
||||
// return true;
|
||||
|
||||
// fully_specified_type
|
||||
if (! acceptFullySpecifiedType(declaredType))
|
||||
@ -334,6 +324,7 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
||||
|
||||
// identifier
|
||||
HlslToken idToken;
|
||||
TIntermAggregate* initializers = nullptr;
|
||||
while (acceptIdentifier(idToken)) {
|
||||
TString* fnName = idToken.string;
|
||||
|
||||
@ -352,7 +343,7 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
||||
parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
|
||||
if (typedefDecl)
|
||||
parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
|
||||
return acceptFunctionDefinition(function, node, node2, attributes);
|
||||
return acceptFunctionDefinition(function, nodeList, attributes);
|
||||
} else {
|
||||
if (typedefDecl)
|
||||
parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
|
||||
@ -421,10 +412,9 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
||||
// Declare the variable and add any initializer code to the AST.
|
||||
// The top-level node is always made into an aggregate, as that's
|
||||
// historically how the AST has been.
|
||||
node = intermediate.growAggregate(node,
|
||||
parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
|
||||
expressionNode),
|
||||
idToken.loc);
|
||||
initializers = intermediate.growAggregate(initializers,
|
||||
parseContext.declareVariable(idToken.loc, *idToken.string, variableType, expressionNode),
|
||||
idToken.loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -436,9 +426,15 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
||||
}
|
||||
};
|
||||
|
||||
// The top-level node is a sequence.
|
||||
if (node != nullptr)
|
||||
node->getAsAggregate()->setOperator(EOpSequence);
|
||||
// The top-level initializer node is a sequence.
|
||||
if (initializers != nullptr)
|
||||
initializers->setOperator(EOpSequence);
|
||||
|
||||
// Add the initializers' aggregate to the nodeList we were handed.
|
||||
if (nodeList)
|
||||
nodeList = intermediate.growAggregate(nodeList, initializers);
|
||||
else
|
||||
nodeList = initializers;
|
||||
|
||||
// SEMICOLON
|
||||
if (! acceptTokenClass(EHTokSemicolon)) {
|
||||
@ -989,7 +985,7 @@ bool HlslGrammar::acceptAnnotations(TQualifier&)
|
||||
break;
|
||||
|
||||
// declaration
|
||||
TIntermNode* node;
|
||||
TIntermNode* node = nullptr;
|
||||
if (! acceptDeclaration(node)) {
|
||||
expected("declaration in annotation");
|
||||
return false;
|
||||
@ -2114,20 +2110,28 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
|
||||
|
||||
// Do the work to create the function definition in addition to
|
||||
// parsing the body (compound_statement).
|
||||
bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, TIntermNode*& node2, const TAttributeMap& attributes)
|
||||
bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& nodeList, const TAttributeMap& attributes)
|
||||
{
|
||||
TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
|
||||
TSourceLoc loc = token.loc;
|
||||
|
||||
// we might get back and entry-point
|
||||
TIntermNode* entryPointNode = nullptr;
|
||||
|
||||
// This does a pushScope()
|
||||
node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes, node2);
|
||||
TIntermNode* functionNode = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes,
|
||||
entryPointNode);
|
||||
|
||||
// compound_statement
|
||||
TIntermNode* functionBody = nullptr;
|
||||
if (! acceptCompoundStatement(functionBody))
|
||||
return false;
|
||||
|
||||
parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
|
||||
parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, functionNode);
|
||||
|
||||
// Hook up the 1 or 2 function definitions.
|
||||
nodeList = intermediate.growAggregate(nodeList, functionNode);
|
||||
nodeList = intermediate.growAggregate(nodeList, entryPointNode);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -2528,7 +2532,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
|
||||
~tFinalize() { parseContext.finalizeFlattening(); }
|
||||
HlslParseContext& parseContext;
|
||||
private:
|
||||
const tFinalize& operator=(const tFinalize& f) { return *this; }
|
||||
const tFinalize& operator=(const tFinalize&) { return *this; }
|
||||
tFinalize(const tFinalize& f) : parseContext(f.parseContext) { }
|
||||
} finalize(parseContext);
|
||||
|
||||
|
@ -65,7 +65,6 @@ namespace glslang {
|
||||
bool acceptIdentifier(HlslToken&);
|
||||
bool acceptCompilationUnit();
|
||||
bool acceptDeclaration(TIntermNode*&);
|
||||
bool acceptDeclaration(TIntermNode*& node1, TIntermNode*& node2);
|
||||
bool acceptControlDeclaration(TIntermNode*& node);
|
||||
bool acceptSamplerDeclarationDX9(TType&);
|
||||
bool acceptSamplerState();
|
||||
@ -88,7 +87,7 @@ namespace glslang {
|
||||
bool acceptStructDeclarationList(TTypeList*&);
|
||||
bool acceptFunctionParameters(TFunction&);
|
||||
bool acceptParameterDeclaration(TFunction&);
|
||||
bool acceptFunctionDefinition(TFunction&, TIntermNode*& node1, TIntermNode*& node2, const TAttributeMap&);
|
||||
bool acceptFunctionDefinition(TFunction&, TIntermNode*& nodeList, const TAttributeMap&);
|
||||
bool acceptParenExpression(TIntermTyped*&);
|
||||
bool acceptExpression(TIntermTyped*&);
|
||||
bool acceptInitializer(TIntermTyped*&);
|
||||
|
@ -1521,6 +1521,8 @@ void HlslParseContext::addInterstageIoToLinkage()
|
||||
// Handle seeing the function prototype in front of a function definition in the grammar.
|
||||
// The body is handled after this function returns.
|
||||
//
|
||||
// Returns an aggregate of parameter-symbol nodes.
|
||||
//
|
||||
TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function,
|
||||
const TAttributeMap& attributes, TIntermNode*& entryPointTree)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user