Commit d5ed0b69 by John Kessenich

HLSL: Mostly non-functional: simplify, rationalize, and generalize the declaration grammar.

parent 07354241
...@@ -37,12 +37,12 @@ gl_FragCoord origin is upper left ...@@ -37,12 +37,12 @@ gl_FragCoord origin is upper left
0:3 'a2' (global float) 0:3 'a2' (global float)
0:3 Constant: 0:3 Constant:
0:3 0.200000 0:3 0.200000
0:? Sequence 0:4 Sequence
0:4 move second child to first child (temp float) 0:4 move second child to first child (temp float)
0:4 'b3' (global float) 0:4 'b3' (global float)
0:4 Constant: 0:4 Constant:
0:4 0.300000 0:4 0.300000
0:? Sequence 0:5 Sequence
0:5 move second child to first child (temp float) 0:5 move second child to first child (temp float)
0:5 'b4' (global float) 0:5 'b4' (global float)
0:5 Constant: 0:5 Constant:
...@@ -164,12 +164,12 @@ gl_FragCoord origin is upper left ...@@ -164,12 +164,12 @@ gl_FragCoord origin is upper left
0:3 'a2' (global float) 0:3 'a2' (global float)
0:3 Constant: 0:3 Constant:
0:3 0.200000 0:3 0.200000
0:? Sequence 0:4 Sequence
0:4 move second child to first child (temp float) 0:4 move second child to first child (temp float)
0:4 'b3' (global float) 0:4 'b3' (global float)
0:4 Constant: 0:4 Constant:
0:4 0.300000 0:4 0.300000
0:? Sequence 0:5 Sequence
0:5 move second child to first child (temp float) 0:5 move second child to first child (temp float)
0:5 'b4' (global float) 0:5 'b4' (global float)
0:5 Constant: 0:5 Constant:
......
...@@ -106,20 +106,19 @@ bool HlslGrammar::acceptCompilationUnit() ...@@ -106,20 +106,19 @@ bool HlslGrammar::acceptCompilationUnit()
} }
// declaration // declaration
// : SEMICOLON // : fully_specified_type declarator_list SEMICOLON
// | fully_specified_type init_declarator_list SEMICOLON
// | fully_specified_type identifier function_parameters post_decls SEMICOLON // function prototype
// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition // | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
// //
// init_declarator_list // declarator_list
// : init_declarator COMMA init_declarator COMMA init_declarator... // : declarator COMMA declarator COMMA declarator... // zero or more declarators
// //
// init_declarator // declarator
// : identifier array_specifier post_decls // : identifier array_specifier post_decls
// | identifier array_specifier post_decls EQUAL assignment_expression // | identifier array_specifier post_decls EQUAL assignment_expression
// | identifier function_parameters post_decls // function prototype
// //
// Parsing has to go pretty far in to know whether it's an init_declarator_list // Parsing has to go pretty far in to know whether it's a variable, prototype, or
// or not, so the implementation below doesn't perfectly divide up the grammar // function definition, so the implementation below doesn't perfectly divide up the grammar
// 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.)
// //
...@@ -129,6 +128,7 @@ bool HlslGrammar::acceptCompilationUnit() ...@@ -129,6 +128,7 @@ bool HlslGrammar::acceptCompilationUnit()
bool HlslGrammar::acceptDeclaration(TIntermNode*& node) bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
{ {
node = nullptr; node = nullptr;
bool list = false;
// fully_specified_type // fully_specified_type
TType type; TType type;
...@@ -139,41 +139,25 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) ...@@ -139,41 +139,25 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
// identifier // identifier
HlslToken idToken; HlslToken idToken;
if (acceptIdentifier(idToken)) { while (acceptIdentifier(idToken)) {
// array_specifier // function_parameters
TArraySizes* arraySizes = nullptr; TFunction* function = new TFunction(idToken.string, type);
acceptArraySpecifier(arraySizes); if (acceptFunctionParameters(*function)) {
// post_decls // post_decls
acceptPostDecls(type); acceptPostDecls(type);
// EQUAL assignment_expression // compound_statement (function body definition) or just a prototype?
TIntermTyped* expressionNode = nullptr; if (peekTokenClass(EHTokLeftBrace)) {
if (acceptTokenClass(EHTokAssign)) { if (list)
if (! acceptAssignmentExpression(expressionNode)) { parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
expected("initializer"); return acceptFunctionDefinition(*function, node);
return false; } else
} parseContext.handleFunctionDeclarator(idToken.loc, *function, true);
} } else {
// a variable declaration
// COMMA
// This means we've been in an init_declarator_list.
// Finish the first init_declarator and recognize the rest of the list.
if (acceptTokenClass(EHTokComma)) {
// init_declarator
// we know have multiple declarations
node = parseContext.declareVariable(idToken.loc, *idToken.string, type, arraySizes, expressionNode);
node = intermediate.makeAggregate(node);
do {
// identifier
if (! acceptIdentifier(idToken)) {
expected("identifier");
return false;
}
// array_specifier // array_specifier
arraySizes = nullptr; TArraySizes* arraySizes = nullptr;
acceptArraySpecifier(arraySizes); acceptArraySpecifier(arraySizes);
// post_decls // post_decls
...@@ -188,55 +172,30 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) ...@@ -188,55 +172,30 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
} }
} }
node = intermediate.growAggregate(node, parseContext.declareVariable(idToken.loc, *idToken.string, type, arraySizes, expressionNode)); // Declare the variable and add any initializer code to the AST.
// The top-level node is always made into an aggregate, as that's
if (acceptTokenClass(EHTokSemicolon)) { // historically how the AST has been.
if (node != nullptr) node = intermediate.growAggregate(node,
node->getAsAggregate()->setOperator(EOpSequence); parseContext.declareVariable(idToken.loc, *idToken.string, type,
return true; arraySizes, expressionNode),
idToken.loc);
} }
if (acceptTokenClass(EHTokComma)) if (acceptTokenClass(EHTokComma)) {
list = true;
continue; continue;
expected(", or ;");
return false;
} while (true);
} }
};
// SEMICOLON // The top-level node is a sequence.
// This also means we've been in an init_declarator_list, but with no COMMA seen.
// Recognize the init_declarator_list, which contains a single declaration.
if (acceptTokenClass(EHTokSemicolon)) {
node = parseContext.declareVariable(idToken.loc, *idToken.string, type, arraySizes, expressionNode);
// use standard AST shape for declarations; just to be safe
node = intermediate.makeAggregate(node);
if (node != nullptr) if (node != nullptr)
node->getAsAggregate()->setOperator(EOpSequence); node->getAsAggregate()->setOperator(EOpSequence);
return true;
}
// function_parameters
TFunction* function = new TFunction(idToken.string, type);
if (acceptFunctionParameters(*function)) {
// post_decls
acceptPostDecls(type);
// compound_statement
if (peekTokenClass(EHTokLeftBrace))
return acceptFunctionDefinition(*function, node);
// SEMICOLON // SEMICOLON
if (acceptTokenClass(EHTokSemicolon)) if (! acceptTokenClass(EHTokSemicolon)) {
return true; expected(";");
return false; return false;
} }
}
// SEMICOLON
if (acceptTokenClass(EHTokSemicolon))
return true;
return true; return true;
} }
......
...@@ -652,12 +652,6 @@ TFunction* HlslParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFu ...@@ -652,12 +652,6 @@ TFunction* HlslParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFu
// If this is a definition, the definition production code will check for redefinitions // If this is a definition, the definition production code will check for redefinitions
// (we don't know at this point if it's a definition or not). // (we don't know at this point if it's a definition or not).
// //
// Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match.
// - except ES 100, which only allows a single prototype
//
// ES 100 does not allow redefining, but does allow overloading of built-in functions.
// ES 300 does not allow redefining or overloading of built-in functions.
//
bool builtIn; bool builtIn;
TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn); TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn);
const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
......
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