HLSL: Add typedef grammar and production.
This commit is contained in:
@@ -108,6 +108,7 @@ bool HlslGrammar::acceptCompilationUnit()
|
||||
// declaration
|
||||
// : fully_specified_type declarator_list SEMICOLON
|
||||
// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
|
||||
// | typedef declaration
|
||||
//
|
||||
// declarator_list
|
||||
// : declarator COMMA declarator COMMA declarator... // zero or more declarators
|
||||
@@ -130,6 +131,9 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
|
||||
node = nullptr;
|
||||
bool list = false;
|
||||
|
||||
// typedef
|
||||
bool typedefDecl = acceptTokenClass(EHTokTypedef);
|
||||
|
||||
// fully_specified_type
|
||||
TType type;
|
||||
if (! acceptFullySpecifiedType(type))
|
||||
@@ -150,9 +154,14 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
|
||||
if (peekTokenClass(EHTokLeftBrace)) {
|
||||
if (list)
|
||||
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);
|
||||
} else
|
||||
} else {
|
||||
if (typedefDecl)
|
||||
parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
|
||||
parseContext.handleFunctionDeclarator(idToken.loc, *function, true);
|
||||
}
|
||||
} else {
|
||||
// a variable declaration
|
||||
|
||||
@@ -166,19 +175,25 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
|
||||
// EQUAL assignment_expression
|
||||
TIntermTyped* expressionNode = nullptr;
|
||||
if (acceptTokenClass(EHTokAssign)) {
|
||||
if (typedefDecl)
|
||||
parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
|
||||
if (! acceptAssignmentExpression(expressionNode)) {
|
||||
expected("initializer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 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, type,
|
||||
arraySizes, expressionNode),
|
||||
idToken.loc);
|
||||
if (typedefDecl)
|
||||
parseContext.declareTypedef(idToken.loc, *idToken.string, type, arraySizes);
|
||||
else {
|
||||
// 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, type,
|
||||
arraySizes, expressionNode),
|
||||
idToken.loc);
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptTokenClass(EHTokComma)) {
|
||||
|
||||
@@ -3018,6 +3018,27 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, const TFu
|
||||
return candidate;
|
||||
}
|
||||
|
||||
//
|
||||
// Do everything necessary to handle a typedef declaration, for a single symbol.
|
||||
//
|
||||
// 'parseType' is the type part of the declaration (to the left)
|
||||
// 'arraySizes' is the arrayness tagged on the identifier (to the right)
|
||||
//
|
||||
void HlslParseContext::declareTypedef(const TSourceLoc& loc, TString& identifier, const TType& parseType, TArraySizes* arraySizes)
|
||||
{
|
||||
TType type;
|
||||
type.deepCopy(parseType);
|
||||
|
||||
// Arrayness is potentially coming both from the type and from the
|
||||
// variable: "int[] a[];" or just one or the other.
|
||||
// Merge it all to the type, so all arrayness is part of the type.
|
||||
arrayDimMerge(type, arraySizes);
|
||||
|
||||
TVariable* typeSymbol = new TVariable(&identifier, type, true);
|
||||
if (! symbolTable.insert(*typeSymbol))
|
||||
error(loc, "name already defined", "typedef", identifier.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// Do everything necessary to handle a variable (non-block) declaration.
|
||||
// Either redeclaring a variable, or making a new one, updating the symbol
|
||||
@@ -3026,7 +3047,7 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, const TFu
|
||||
// Returns a subtree node that computes an initializer, if needed.
|
||||
// Returns nullptr if there is no code to execute for initialization.
|
||||
//
|
||||
// 'publicType' is the type part of the declaration (to the left)
|
||||
// 'parseType' is the type part of the declaration (to the left)
|
||||
// 'arraySizes' is the arrayness tagged on the identifier (to the right)
|
||||
//
|
||||
TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TType& parseType, TArraySizes* arraySizes, TIntermTyped* initializer)
|
||||
@@ -3036,7 +3057,7 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
|
||||
if (type.isImplicitlySizedArray()) {
|
||||
// Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
|
||||
// of different sizes, for this case sharing the shallow copy of arrayness
|
||||
// with the publicType oversubscribes it, so get a deep copy of the arrayness.
|
||||
// with the parseType oversubscribes it, so get a deep copy of the arrayness.
|
||||
type.newArraySizes(*parseType.getArraySizes());
|
||||
}
|
||||
|
||||
@@ -3045,7 +3066,7 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
|
||||
|
||||
// Check for redeclaration of built-ins and/or attempting to declare a reserved name
|
||||
bool newDeclaration = false; // true if a new entry gets added to the symbol table
|
||||
TSymbol* symbol = nullptr; // = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers, newDeclaration);
|
||||
TSymbol* symbol = nullptr; // = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), parseType.shaderQualifiers, newDeclaration);
|
||||
|
||||
inheritGlobalDefaults(type.getQualifier());
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ public:
|
||||
void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
|
||||
|
||||
const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
||||
void declareTypedef(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0);
|
||||
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
|
||||
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator);
|
||||
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
|
||||
|
||||
Reference in New Issue
Block a user