HLSL: Member-functions: capture body token stream for deferred syntax/semantics.
This is needed for accessing types/variables within a member function body that are not known until after the struct is finished being declared. However, that funtionality is not yet present, this is just the deferred processing, which is working for static member functions.
This commit is contained in:
parent
088d52bac2
commit
b16f7e6819
@ -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.1901"
|
||||
#define GLSLANG_REVISION "Overload400-PrecQual.1902"
|
||||
#define GLSLANG_DATE "11-Mar-2017"
|
||||
|
@ -350,7 +350,7 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
|
||||
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(declarator, nodeList);
|
||||
return acceptFunctionDefinition(declarator, nodeList, nullptr);
|
||||
} else {
|
||||
if (typedefDecl)
|
||||
parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
|
||||
@ -1936,10 +1936,15 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
|
||||
typeList = new TTypeList();
|
||||
HlslToken idToken;
|
||||
|
||||
// Save these away for each member function so they can be processed after
|
||||
// all member variables/types have been declared.
|
||||
TVector<TVector<HlslToken>*> memberBodies;
|
||||
TVector<TFunctionDeclarator> declarators;
|
||||
|
||||
do {
|
||||
// success on seeing the RIGHT_BRACE coming up
|
||||
if (peekTokenClass(EHTokRightBrace))
|
||||
return true;
|
||||
break;
|
||||
|
||||
// struct_declaration
|
||||
|
||||
@ -1963,8 +1968,13 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
|
||||
if (peekTokenClass(EHTokLeftParen)) {
|
||||
// function_parameters
|
||||
if (!declarator_list) {
|
||||
declarators.resize(declarators.size() + 1);
|
||||
// request a token stream for deferred processing
|
||||
TVector<HlslToken>* deferredTokens = new TVector<HlslToken>;
|
||||
functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, typeName, memberType,
|
||||
*idToken.string);
|
||||
*idToken.string, declarators.back(),
|
||||
deferredTokens);
|
||||
memberBodies.push_back(deferredTokens);
|
||||
if (functionDefinitionAccepted)
|
||||
break;
|
||||
}
|
||||
@ -2016,6 +2026,16 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
|
||||
}
|
||||
|
||||
} while (true);
|
||||
|
||||
// parse member-function bodies now
|
||||
for (int b = 0; b < (int)memberBodies.size(); ++b) {
|
||||
pushTokenStream(memberBodies[b]);
|
||||
if (! acceptFunctionBody(declarators[b], nodeList))
|
||||
return false;
|
||||
popTokenStream();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// member_function_definition
|
||||
@ -2024,14 +2044,14 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
|
||||
// Expects type to have EvqGlobal for a static member and
|
||||
// EvqTemporary for non-static member.
|
||||
bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TString& typeName,
|
||||
const TType& type, const TString& memberName)
|
||||
const TType& type, const TString& memberName,
|
||||
TFunctionDeclarator& declarator, TVector<HlslToken>* deferredTokens)
|
||||
{
|
||||
// watch early returns...
|
||||
parseContext.pushThis(typeName);
|
||||
bool accepted = false;
|
||||
|
||||
TString* functionName = parseContext.getFullMemberFunctionName(memberName, type.getQualifier().storage == EvqGlobal);
|
||||
TFunctionDeclarator declarator;
|
||||
declarator.function = new TFunction(functionName, type);
|
||||
|
||||
// function_parameters
|
||||
@ -2047,7 +2067,7 @@ bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const T
|
||||
}
|
||||
|
||||
declarator.loc = token.loc;
|
||||
accepted = acceptFunctionDefinition(declarator, nodeList);
|
||||
accepted = acceptFunctionDefinition(declarator, nodeList, deferredTokens);
|
||||
}
|
||||
} else
|
||||
expected("function parameter list");
|
||||
@ -2183,10 +2203,18 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
|
||||
|
||||
// Do the work to create the function definition in addition to
|
||||
// parsing the body (compound_statement).
|
||||
bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
|
||||
//
|
||||
// If 'deferredTokens' are passed in, just get the token stream,
|
||||
// don't process.
|
||||
//
|
||||
bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
|
||||
TVector<HlslToken>* deferredTokens)
|
||||
{
|
||||
parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
|
||||
|
||||
if (deferredTokens)
|
||||
return captureBlockTokens(*deferredTokens);
|
||||
else
|
||||
return acceptFunctionBody(declarator, nodeList);
|
||||
}
|
||||
|
||||
@ -3513,4 +3541,37 @@ bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
return found;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the stream of tokens from the scanner, but skip all syntactic/semantic
|
||||
// processing.
|
||||
//
|
||||
bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
|
||||
{
|
||||
if (! peekTokenClass(EHTokLeftBrace))
|
||||
return false;
|
||||
|
||||
int braceCount = 0;
|
||||
|
||||
do {
|
||||
switch (peek()) {
|
||||
case EHTokLeftBrace:
|
||||
++braceCount;
|
||||
break;
|
||||
case EHTokRightBrace:
|
||||
--braceCount;
|
||||
break;
|
||||
case EHTokNone:
|
||||
// End of input before balance { } is bad...
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
tokens.push_back(token);
|
||||
advanceToken();
|
||||
} while (braceCount > 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
@ -89,10 +89,11 @@ namespace glslang {
|
||||
bool acceptStruct(TType&, TIntermNode*& nodeList);
|
||||
bool acceptStructDeclarationList(TTypeList*&, TIntermNode*& nodeList, const TString& typeName);
|
||||
bool acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TString& typeName,
|
||||
const TType&, const TString& memberName);
|
||||
const TType&, const TString& memberName, TFunctionDeclarator&,
|
||||
TVector<HlslToken>* deferredTokens);
|
||||
bool acceptFunctionParameters(TFunction&);
|
||||
bool acceptParameterDeclaration(TFunction&);
|
||||
bool acceptFunctionDefinition(TFunctionDeclarator&, TIntermNode*& nodeList);
|
||||
bool acceptFunctionDefinition(TFunctionDeclarator&, TIntermNode*& nodeList, TVector<HlslToken>* deferredTokens);
|
||||
bool acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList);
|
||||
bool acceptParenExpression(TIntermTyped*&);
|
||||
bool acceptExpression(TIntermTyped*&);
|
||||
@ -123,6 +124,8 @@ namespace glslang {
|
||||
bool acceptPostDecls(TQualifier&);
|
||||
bool acceptDefaultParameterDeclaration(const TType&, TIntermTyped*&);
|
||||
|
||||
bool captureBlockTokens(TVector<HlslToken>& tokens);
|
||||
|
||||
HlslParseContext& parseContext; // state of parsing and helper functions for building the intermediate
|
||||
TIntermediate& intermediate; // the final product, the intermediate representation, includes the AST
|
||||
};
|
||||
|
@ -64,14 +64,56 @@ HlslToken HlslTokenStream::popTokenBuffer()
|
||||
return tokenBuffer[tokenBufferPos];
|
||||
}
|
||||
|
||||
//
|
||||
// Make a new source of tokens, not from the source, but from an
|
||||
// already pre-processed token stream.
|
||||
//
|
||||
// This interrupts current token processing which must be restored
|
||||
// later. Some simplifying assumptions are made (and asserted).
|
||||
//
|
||||
void HlslTokenStream::pushTokenStream(const TVector<HlslToken>* tokens)
|
||||
{
|
||||
// not yet setup to interrupt a stream that has been receded
|
||||
// and not yet reconsumed
|
||||
assert(preTokenStackSize == 0);
|
||||
|
||||
// save current state
|
||||
currentTokenStack.push_back(token);
|
||||
|
||||
// set up new token stream
|
||||
tokenStreamStack.push_back(tokens);
|
||||
|
||||
// start position at first token:
|
||||
token = (*tokens)[0];
|
||||
tokenPosition.push_back(0);
|
||||
}
|
||||
|
||||
// Undo pushTokenStream(), see above
|
||||
void HlslTokenStream::popTokenStream()
|
||||
{
|
||||
tokenStreamStack.pop_back();
|
||||
tokenPosition.pop_back();
|
||||
token = currentTokenStack.back();
|
||||
currentTokenStack.pop_back();
|
||||
}
|
||||
|
||||
// Load 'token' with the next token in the stream of tokens.
|
||||
void HlslTokenStream::advanceToken()
|
||||
{
|
||||
pushTokenBuffer(token);
|
||||
if (preTokenStackSize > 0)
|
||||
token = popPreToken();
|
||||
else
|
||||
scanner.tokenize(token);
|
||||
else {
|
||||
if (tokenStreamStack.size() == 0)
|
||||
scanner.tokenize(token);
|
||||
else {
|
||||
++tokenPosition.back();
|
||||
if (tokenPosition.back() >= (int)tokenStreamStack.back()->size())
|
||||
token.tokenClass = EHTokNone;
|
||||
else
|
||||
token = (*tokenStreamStack.back())[tokenPosition.back()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HlslTokenStream::recedeToken()
|
||||
|
@ -54,6 +54,9 @@ namespace glslang {
|
||||
bool peekTokenClass(EHlslTokenClass) const;
|
||||
glslang::TBuiltInVariable mapSemantic(const TString& semantic) { return scanner.mapSemantic(semantic); }
|
||||
|
||||
void pushTokenStream(const TVector<HlslToken>* tokens);
|
||||
void popTokenStream();
|
||||
|
||||
protected:
|
||||
HlslToken token; // the token we are currently looking at, but have not yet accepted
|
||||
|
||||
@ -61,7 +64,10 @@ namespace glslang {
|
||||
HlslTokenStream();
|
||||
HlslTokenStream& operator=(const HlslTokenStream&);
|
||||
|
||||
HlslScanContext& scanner; // lexical scanner, to get next token
|
||||
HlslScanContext& scanner; // lexical scanner, to get next token from source file
|
||||
TVector<const TVector<HlslToken>*> tokenStreamStack; // for getting the next token from an existing vector of tokens
|
||||
TVector<int> tokenPosition;
|
||||
TVector<HlslToken> currentTokenStack;
|
||||
|
||||
// This is the number of tokens we can recedeToken() over.
|
||||
static const int tokenBufferSize = 2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user