HLSL: Add basic declaration syntax and AST generation.
authorJohn Kessenich <cepheus@frii.com>
Sun, 13 Mar 2016 03:24:24 +0000 (20:24 -0700)
committerJohn Kessenich <cepheus@frii.com>
Sun, 13 Mar 2016 04:40:38 +0000 (21:40 -0700)
Test/baseResults/hlsl.frag.out
Test/hlsl.frag
hlsl/hlslGrammar.cpp
hlsl/hlslGrammar.h

index bc2e035..bb5e5a7 100644 (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
index 6631404..8ed18aa 100644 (file)
@@ -1,11 +1,11 @@
-//float4x4 World;\r
-//float4x4 View;\r
-//float4x4 Projection;\r
-//\r
-//float4 AmbientColor = float4(1, 1, 1, 1);\r
-//float AmbientIntensity = 0.1;\r
-//\r
-//float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0\r
-//{\r
-//    return AmbientColor * AmbientIntensity;\r
-//}\r
+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;
+//}
index 9673658..bbf3c99 100755 (executable)
@@ -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()
 {
+    // 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
index c445f03..3e042ff 100755 (executable)
@@ -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;