HLSL: Add basic declaration syntax and AST generation.

This commit is contained in:
John Kessenich 2016-03-12 20:24:24 -07:00
parent e01a9bc8c0
commit 87142c71fb
4 changed files with 335 additions and 14 deletions

View File

@ -5,7 +5,7 @@ Linked fragment stage:
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 6
// Id's are bound by 17
Capability Shader
1: ExtInstImport "GLSL.std.450"
@ -14,8 +14,24 @@ Linked fragment stage:
ExecutionMode 4 OriginUpperLeft
Source HLSL 100
Name 4 "PixelShaderFunction"
Name 10 "World"
Name 11 "View"
Name 12 "Projection"
Name 14 "AmbientColor"
Name 16 "AmbientIntensity"
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypeMatrix 7(fvec4) 4
9: TypePointer Function 8
13: TypePointer Function 7(fvec4)
15: TypePointer Function 6(float)
4(PixelShaderFunction): 2 Function None 3
5: Label
10(World): 9(ptr) Variable Function
11(View): 9(ptr) Variable Function
12(Projection): 9(ptr) Variable Function
14(AmbientColor): 13(ptr) Variable Function
16(AmbientIntensity): 15(ptr) Variable Function
FunctionEnd

View File

@ -1,10 +1,10 @@
//float4x4 World;
//float4x4 View;
//float4x4 Projection;
//
//float4 AmbientColor = float4(1, 1, 1, 1);
//float AmbientIntensity = 0.1;
//
float4x4 World;
float4x4 View;
float4x4 Projection;
float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 0.1;
//float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
//{
// return AmbientColor * AmbientIntensity;

View File

@ -83,11 +83,308 @@ bool HlslGrammar::acceptCompilationUnit()
}
// declaration
// : dummy stub
// : SEMICOLON
// : fully_specified_type ;
// | fully_specified_type identifier ;
// | fully_specified_type identifier = expression ;
// | fully_specified_type identifier function_parameters ; // function prototype
// | fully_specified_type function_parameters compound_statement // function definition
//
bool HlslGrammar::acceptDeclaration()
{
advanceToken();
// fully_specified_type
TType type;
if (! acceptFullySpecifiedType(type))
return false;
// identifier
if (token.tokenClass == EHTokIdentifier) {
TSourceLoc declLoc = token.loc;
TString* declName = token.string;
advanceToken();
// = expression
TIntermTyped* expressionNode = nullptr;
if (acceptTokenClass(EHTokEqual)) {
if (! acceptExpression(expressionNode)) {
expected("initializer");
return false;
}
}
// ;
if (acceptTokenClass(EHTokSemicolon)) {
parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
return true;
}
}
// no identifier, just ;
if (acceptTokenClass(EHTokSemicolon))
return true;
return true;
}
// fully_specified_type
// : type_specifier
// | type_qualifier type_specifier
//
bool HlslGrammar::acceptFullySpecifiedType(TType& type)
{
// type_qualifier
TQualifier qualifier;
qualifier.clear();
acceptQualifier(qualifier);
// type_specifier
if (! acceptType(type))
return false;
type.getQualifier() = qualifier;
return true;
}
// If token is a qualifier, return its token class and advance to the next
// qualifier. Otherwise, return false, and don't advance.
void HlslGrammar::acceptQualifier(TQualifier& qualifier)
{
switch (token.tokenClass) {
case EHTokUniform:
qualifier.storage = EvqUniform;
break;
case EHTokConst:
qualifier.storage = EvqConst;
break;
default:
return;
}
advanceToken();
}
// If token is for a type, update 'type' with the type information,
// and return true and advance.
// Otherwise, return false, and don't advance
bool HlslGrammar::acceptType(TType& type)
{
if (! token.isType)
return false;
switch (token.tokenClass) {
case EHTokInt:
case EHTokInt1:
case EHTokDword:
new(&type) TType(EbtInt);
break;
case EHTokFloat:
case EHTokFloat1:
new(&type) TType(EbtFloat);
break;
case EHTokFloat2:
new(&type) TType(EbtFloat, EvqTemporary, 2);
break;
case EHTokFloat3:
new(&type) TType(EbtFloat, EvqTemporary, 3);
break;
case EHTokFloat4:
new(&type) TType(EbtFloat, EvqTemporary, 4);
break;
case EHTokInt2:
new(&type) TType(EbtInt, EvqTemporary, 2);
break;
case EHTokInt3:
new(&type) TType(EbtInt, EvqTemporary, 3);
break;
case EHTokInt4:
new(&type) TType(EbtInt, EvqTemporary, 4);
break;
case EHTokBool2:
new(&type) TType(EbtBool, EvqTemporary, 2);
break;
case EHTokBool3:
new(&type) TType(EbtBool, EvqTemporary, 3);
break;
case EHTokBool4:
new(&type) TType(EbtBool, EvqTemporary, 4);
break;
case EHTokFloat2x2:
new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
break;
case EHTokFloat2x3:
new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
break;
case EHTokFloat2x4:
new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
break;
case EHTokFloat3x2:
new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
break;
case EHTokFloat3x3:
new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
break;
case EHTokFloat3x4:
new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
break;
case EHTokFloat4x2:
new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
break;
case EHTokFloat4x3:
new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
break;
case EHTokFloat4x4:
new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
break;
default:
return false;
}
advanceToken();
return true;
}
// expression
// : identifier
// | ( expression )
// | type(...) // constructor
// | literal
// | identifier + identifier
//
bool HlslGrammar::acceptExpression(TIntermTyped*& node)
{
// identifier
if (token.tokenClass == EHTokIdentifier) {
node = parseContext.handleVariable(token.loc, token.symbol, token.string);
return true;
}
// ( expression )
if (acceptTokenClass(EHTokLeftParen)) {
if (! acceptExpression(node)) {
expected("expression");
return false;
}
if (! acceptTokenClass(EHTokRightParen)) {
expected("right parenthesis");
return false;
}
return true;
}
// literal
if (acceptLiteral(node))
return true;
// type(...) // constructor
TType type;
if (acceptType(type)) {
TIntermSequence* arguments;
if (! acceptArguments(arguments)) {
expected("constructor arguments");
return false;
}
return true;
}
// identifier + identifier
if (token.tokenClass == EHTokIdentifier) {
TIntermTyped* left = parseContext.handleVariable(token.loc, token.symbol, token.string);
advanceToken();
// operator
TOperator op;
if (! acceptOperator(op))
return false;
TSourceLoc loc = token.loc;
// right
if (token.tokenClass == EHTokIdentifier) {
TIntermTyped* right = parseContext.handleVariable(token.loc, token.symbol, token.string);
advanceToken();
node = parseContext.intermediate.addBinaryMath(op, left, right, loc);
} else
return false;
} else
return false;
return true;
}
// arguments
// : ( expression , expression, ... )
//
bool HlslGrammar::acceptArguments(TIntermSequence*& arguments)
{
if (! acceptTokenClass(EHTokLeftParen))
return false;
do {
TIntermTyped* arg;
if (! acceptExpression(arg))
break;
if (! acceptTokenClass(EHTokComma))
break;
} while (true);
if (! acceptTokenClass(EHTokRightParen)) {
expected("right parenthesis");
return false;
}
return true;
}
bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
{
switch (token.tokenClass) {
case EHTokIntConstant:
node = parseContext.intermediate.addConstantUnion(token.i, token.loc, true);
break;
case EHTokFloatConstant:
node = parseContext.intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
break;
case EHTokDoubleConstant:
node = parseContext.intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
break;
case EHTokBoolConstant:
node = parseContext.intermediate.addConstantUnion(token.b, token.loc, true);
break;
default:
return false;
}
advanceToken();
return true;
}
bool HlslGrammar::acceptOperator(TOperator& op)
{
switch (token.tokenClass) {
case EHTokPlus:
op = EOpAdd;
break;
default:
return false;
}
advanceToken();
return true;
}
bool HlslGrammar::acceptCompoundStatement()
{
return false;
}
} // end namespace glslang

View File

@ -56,6 +56,14 @@ namespace glslang {
bool acceptCompilationUnit();
bool acceptDeclaration();
bool acceptFullySpecifiedType(TType&);
void acceptQualifier(TQualifier&);
bool acceptType(TType&);
bool acceptCompoundStatement();
bool acceptExpression(TIntermTyped*&);
bool acceptArguments(TIntermSequence*&);
bool acceptLiteral(TIntermTyped*&);
bool acceptOperator(TOperator& op);
HlslScanContext& scanContext;
HlslParseContext& parseContext;