From 87142c71fbb16b77d187c00fa6f390677483d806 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sat, 12 Mar 2016 20:24:24 -0700 Subject: [PATCH] HLSL: Add basic declaration syntax and AST generation. --- Test/baseResults/hlsl.frag.out | 18 +- Test/hlsl.frag | 22 +-- hlsl/hlslGrammar.cpp | 301 ++++++++++++++++++++++++++++++++- hlsl/hlslGrammar.h | 8 + 4 files changed, 335 insertions(+), 14 deletions(-) diff --git a/Test/baseResults/hlsl.frag.out b/Test/baseResults/hlsl.frag.out index bc2e035d2..bb5e5a7ce 100644 --- a/Test/baseResults/hlsl.frag.out +++ b/Test/baseResults/hlsl.frag.out @@ -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 diff --git a/Test/hlsl.frag b/Test/hlsl.frag index 663140416..8ed18aa83 100644 --- a/Test/hlsl.frag +++ b/Test/hlsl.frag @@ -1,11 +1,11 @@ -//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; -//} +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; +//} diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 9673658c8..bbf3c999d 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -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 diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h index c445f0390..3e042ffe5 100755 --- a/hlsl/hlslGrammar.h +++ b/hlsl/hlslGrammar.h @@ -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;