diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index d6678ff8..45eb6f70 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -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" diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 39de92e7..166141b3 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -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*> memberBodies; + TVector 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* deferredTokens = new TVector; 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* 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* 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& 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 diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h index 05b7206b..e95fab0d 100755 --- a/hlsl/hlslGrammar.h +++ b/hlsl/hlslGrammar.h @@ -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* deferredTokens); bool acceptFunctionParameters(TFunction&); bool acceptParameterDeclaration(TFunction&); - bool acceptFunctionDefinition(TFunctionDeclarator&, TIntermNode*& nodeList); + bool acceptFunctionDefinition(TFunctionDeclarator&, TIntermNode*& nodeList, TVector* 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& tokens); + HlslParseContext& parseContext; // state of parsing and helper functions for building the intermediate TIntermediate& intermediate; // the final product, the intermediate representation, includes the AST }; diff --git a/hlsl/hlslTokenStream.cpp b/hlsl/hlslTokenStream.cpp index b458ba47..5d9311cf 100755 --- a/hlsl/hlslTokenStream.cpp +++ b/hlsl/hlslTokenStream.cpp @@ -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* 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() diff --git a/hlsl/hlslTokenStream.h b/hlsl/hlslTokenStream.h index 70cfc446..333fef96 100755 --- a/hlsl/hlslTokenStream.h +++ b/hlsl/hlslTokenStream.h @@ -54,6 +54,9 @@ namespace glslang { bool peekTokenClass(EHlslTokenClass) const; glslang::TBuiltInVariable mapSemantic(const TString& semantic) { return scanner.mapSemantic(semantic); } + void pushTokenStream(const TVector* 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*> tokenStreamStack; // for getting the next token from an existing vector of tokens + TVector tokenPosition; + TVector currentTokenStack; // This is the number of tokens we can recedeToken() over. static const int tokenBufferSize = 2;