mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-10 04:20:06 +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 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).
|
// For the date, it uses the current date (when then script is run).
|
||||||
|
|
||||||
#define GLSLANG_REVISION "Overload400-PrecQual.1881"
|
#define GLSLANG_REVISION "Overload400-PrecQual.1882"
|
||||||
#define GLSLANG_DATE "06-Mar-2017"
|
#define GLSLANG_DATE "07-Mar-2017"
|
||||||
|
@ -1158,15 +1158,15 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
TIntermAggregate* aggNode = nullptr;
|
TIntermAggregate* aggNode = nullptr;
|
||||||
if (left)
|
if (left != nullptr)
|
||||||
aggNode = left->getAsAggregate();
|
aggNode = left->getAsAggregate();
|
||||||
if (! aggNode || aggNode->getOp() != EOpNull) {
|
if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
|
||||||
aggNode = new TIntermAggregate;
|
aggNode = new TIntermAggregate;
|
||||||
if (left)
|
if (left != nullptr)
|
||||||
aggNode->getSequence().push_back(left);
|
aggNode->getSequence().push_back(left);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (right)
|
if (right != nullptr)
|
||||||
aggNode->getSequence().push_back(right);
|
aggNode->getSequence().push_back(right);
|
||||||
|
|
||||||
return aggNode;
|
return aggNode;
|
||||||
|
@ -131,18 +131,13 @@ bool HlslGrammar::acceptCompilationUnit()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// externalDeclaration
|
// externalDeclaration
|
||||||
TIntermNode* declarationNode1;
|
if (! acceptDeclaration(unitNode))
|
||||||
TIntermNode* declarationNode2 = nullptr; // sometimes the grammar for a single declaration creates two
|
|
||||||
if (! acceptDeclaration(declarationNode1, declarationNode2))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// hook it up
|
|
||||||
unitNode = intermediate.growAggregate(unitNode, declarationNode1);
|
|
||||||
if (declarationNode2 != nullptr)
|
|
||||||
unitNode = intermediate.growAggregate(unitNode, declarationNode2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set root of AST
|
// set root of AST
|
||||||
|
if (unitNode && !unitNode->getAsAggregate())
|
||||||
|
unitNode = intermediate.growAggregate(nullptr, unitNode);
|
||||||
intermediate.setTreeRoot(unitNode);
|
intermediate.setTreeRoot(unitNode);
|
||||||
|
|
||||||
return true;
|
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
|
// as above. (The 'identifier' in the first item in init_declarator list is the
|
||||||
// same as 'identifier' for function declarations.)
|
// same as 'identifier' for function declarations.)
|
||||||
//
|
//
|
||||||
// 'node' could get populated if the declaration creates code, like an initializer
|
// This can generate more than one subtree, one per initializer or a function body.
|
||||||
// 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
|
// If 'nodeList' is passed in as non-null, it must an aggregate to extend for
|
||||||
// leads to two subtrees that need to be peers higher up.
|
// 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;
|
bool list = false;
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
@ -324,9 +315,8 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
|||||||
// HLSL shaders, this will have to be a master level switch
|
// 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
|
// 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
|
// For that reason, this line is commented out
|
||||||
|
// if (acceptSamplerDeclarationDX9(declaredType))
|
||||||
// if (acceptSamplerDeclarationDX9(declaredType))
|
// return true;
|
||||||
// return true;
|
|
||||||
|
|
||||||
// fully_specified_type
|
// fully_specified_type
|
||||||
if (! acceptFullySpecifiedType(declaredType))
|
if (! acceptFullySpecifiedType(declaredType))
|
||||||
@ -334,6 +324,7 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
|||||||
|
|
||||||
// identifier
|
// identifier
|
||||||
HlslToken idToken;
|
HlslToken idToken;
|
||||||
|
TIntermAggregate* initializers = nullptr;
|
||||||
while (acceptIdentifier(idToken)) {
|
while (acceptIdentifier(idToken)) {
|
||||||
TString* fnName = idToken.string;
|
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", "{", "");
|
parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
|
||||||
if (typedefDecl)
|
if (typedefDecl)
|
||||||
parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
|
parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
|
||||||
return acceptFunctionDefinition(function, node, node2, attributes);
|
return acceptFunctionDefinition(function, nodeList, attributes);
|
||||||
} else {
|
} else {
|
||||||
if (typedefDecl)
|
if (typedefDecl)
|
||||||
parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
|
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.
|
// Declare the variable and add any initializer code to the AST.
|
||||||
// The top-level node is always made into an aggregate, as that's
|
// The top-level node is always made into an aggregate, as that's
|
||||||
// historically how the AST has been.
|
// historically how the AST has been.
|
||||||
node = intermediate.growAggregate(node,
|
initializers = intermediate.growAggregate(initializers,
|
||||||
parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
|
parseContext.declareVariable(idToken.loc, *idToken.string, variableType, expressionNode),
|
||||||
expressionNode),
|
idToken.loc);
|
||||||
idToken.loc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,9 +426,15 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// The top-level node is a sequence.
|
// The top-level initializer node is a sequence.
|
||||||
if (node != nullptr)
|
if (initializers != nullptr)
|
||||||
node->getAsAggregate()->setOperator(EOpSequence);
|
initializers->setOperator(EOpSequence);
|
||||||
|
|
||||||
|
// Add the initializers' aggregate to the nodeList we were handed.
|
||||||
|
if (nodeList)
|
||||||
|
nodeList = intermediate.growAggregate(nodeList, initializers);
|
||||||
|
else
|
||||||
|
nodeList = initializers;
|
||||||
|
|
||||||
// SEMICOLON
|
// SEMICOLON
|
||||||
if (! acceptTokenClass(EHTokSemicolon)) {
|
if (! acceptTokenClass(EHTokSemicolon)) {
|
||||||
@ -989,7 +985,7 @@ bool HlslGrammar::acceptAnnotations(TQualifier&)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// declaration
|
// declaration
|
||||||
TIntermNode* node;
|
TIntermNode* node = nullptr;
|
||||||
if (! acceptDeclaration(node)) {
|
if (! acceptDeclaration(node)) {
|
||||||
expected("declaration in annotation");
|
expected("declaration in annotation");
|
||||||
return false;
|
return false;
|
||||||
@ -2114,20 +2110,28 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
|
|||||||
|
|
||||||
// Do the work to create the function definition in addition to
|
// Do the work to create the function definition in addition to
|
||||||
// parsing the body (compound_statement).
|
// 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 */);
|
TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
|
||||||
TSourceLoc loc = token.loc;
|
TSourceLoc loc = token.loc;
|
||||||
|
|
||||||
|
// we might get back and entry-point
|
||||||
|
TIntermNode* entryPointNode = nullptr;
|
||||||
|
|
||||||
// This does a pushScope()
|
// This does a pushScope()
|
||||||
node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes, node2);
|
TIntermNode* functionNode = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes,
|
||||||
|
entryPointNode);
|
||||||
|
|
||||||
// compound_statement
|
// compound_statement
|
||||||
TIntermNode* functionBody = nullptr;
|
TIntermNode* functionBody = nullptr;
|
||||||
if (! acceptCompoundStatement(functionBody))
|
if (! acceptCompoundStatement(functionBody))
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2528,7 +2532,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
|
|||||||
~tFinalize() { parseContext.finalizeFlattening(); }
|
~tFinalize() { parseContext.finalizeFlattening(); }
|
||||||
HlslParseContext& parseContext;
|
HlslParseContext& parseContext;
|
||||||
private:
|
private:
|
||||||
const tFinalize& operator=(const tFinalize& f) { return *this; }
|
const tFinalize& operator=(const tFinalize&) { return *this; }
|
||||||
tFinalize(const tFinalize& f) : parseContext(f.parseContext) { }
|
tFinalize(const tFinalize& f) : parseContext(f.parseContext) { }
|
||||||
} finalize(parseContext);
|
} finalize(parseContext);
|
||||||
|
|
||||||
|
@ -65,7 +65,6 @@ namespace glslang {
|
|||||||
bool acceptIdentifier(HlslToken&);
|
bool acceptIdentifier(HlslToken&);
|
||||||
bool acceptCompilationUnit();
|
bool acceptCompilationUnit();
|
||||||
bool acceptDeclaration(TIntermNode*&);
|
bool acceptDeclaration(TIntermNode*&);
|
||||||
bool acceptDeclaration(TIntermNode*& node1, TIntermNode*& node2);
|
|
||||||
bool acceptControlDeclaration(TIntermNode*& node);
|
bool acceptControlDeclaration(TIntermNode*& node);
|
||||||
bool acceptSamplerDeclarationDX9(TType&);
|
bool acceptSamplerDeclarationDX9(TType&);
|
||||||
bool acceptSamplerState();
|
bool acceptSamplerState();
|
||||||
@ -88,7 +87,7 @@ namespace glslang {
|
|||||||
bool acceptStructDeclarationList(TTypeList*&);
|
bool acceptStructDeclarationList(TTypeList*&);
|
||||||
bool acceptFunctionParameters(TFunction&);
|
bool acceptFunctionParameters(TFunction&);
|
||||||
bool acceptParameterDeclaration(TFunction&);
|
bool acceptParameterDeclaration(TFunction&);
|
||||||
bool acceptFunctionDefinition(TFunction&, TIntermNode*& node1, TIntermNode*& node2, const TAttributeMap&);
|
bool acceptFunctionDefinition(TFunction&, TIntermNode*& nodeList, const TAttributeMap&);
|
||||||
bool acceptParenExpression(TIntermTyped*&);
|
bool acceptParenExpression(TIntermTyped*&);
|
||||||
bool acceptExpression(TIntermTyped*&);
|
bool acceptExpression(TIntermTyped*&);
|
||||||
bool acceptInitializer(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.
|
// Handle seeing the function prototype in front of a function definition in the grammar.
|
||||||
// The body is handled after this function returns.
|
// The body is handled after this function returns.
|
||||||
//
|
//
|
||||||
|
// Returns an aggregate of parameter-symbol nodes.
|
||||||
|
//
|
||||||
TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function,
|
TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function,
|
||||||
const TAttributeMap& attributes, TIntermNode*& entryPointTree)
|
const TAttributeMap& attributes, TIntermNode*& entryPointTree)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user