HLSL: allow "sample" in expressions.
Unlike other qualifiers, HLSL allows "sample" to be either a qualifier keyword or an identifier (e.g, a variable or function name). A fix to allow this was made a while ago, but that fix was insufficient when 'sample' was used in an expression. The problem was around the initial ambiguity between: sample float a; // "sample" is part of a fully specified type and sample.xyz; // sample is a keyword in a dot expression Both start the same. The "sample" was being accepted as a qualifier before enough further parsing was done to determine we were not a declaration after all. This consumed the token, causing it to fail for its real purpose. Now, when accepting a fully specified type, the token is pushed back onto the stack if the thing is not a fully specified type. This leaves it available for subsequent purposes. Changed the "hlsl.identifier.sample.frag" test to exercise this situation, distilled down from a production shaders.
This commit is contained in:
@@ -90,10 +90,11 @@ bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
|
||||
// as "linear" or "centroid" NOT valid identifiers. This code special cases "sample",
|
||||
// so e.g, "int sample;" is accepted.
|
||||
if (peekTokenClass(EHTokSample)) {
|
||||
idToken.string = NewPoolTString("sample");
|
||||
idToken.tokenClass = EHTokIdentifier;
|
||||
idToken.symbol = nullptr;
|
||||
idToken.loc = token.loc;
|
||||
token.string = NewPoolTString("sample");
|
||||
token.tokenClass = EHTokIdentifier;
|
||||
token.symbol = nullptr;
|
||||
|
||||
idToken = token;
|
||||
advanceToken();
|
||||
return true;
|
||||
}
|
||||
@@ -475,8 +476,15 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type)
|
||||
TSourceLoc loc = token.loc;
|
||||
|
||||
// type_specifier
|
||||
if (! acceptType(type))
|
||||
if (! acceptType(type)) {
|
||||
// If this is not a type, we may have inadvertently gone down a wrong path
|
||||
// py parsing "sample", which can be treated like either an identifier or a
|
||||
// qualifier. Back it out, if we did.
|
||||
if (qualifier.sample)
|
||||
recedeToken();
|
||||
|
||||
return false;
|
||||
}
|
||||
if (type.getBasicType() == EbtBlock) {
|
||||
// the type was a block, which set some parts of the qualifier
|
||||
parseContext.mergeQualifiers(type.getQualifier(), qualifier);
|
||||
@@ -2203,7 +2211,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
|
||||
} else if (acceptIdentifier(idToken)) {
|
||||
// identifier or function_call name
|
||||
if (! peekTokenClass(EHTokLeftParen)) {
|
||||
node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string);
|
||||
node = parseContext.handleVariable(idToken.loc, idToken.symbol, idToken.string);
|
||||
} else if (acceptFunctionCall(idToken, node)) {
|
||||
// function_call (nothing else to do yet)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user