Add parser support for highp/mediump Tokens in vardecls.

These parse into new modifier bits; the IR generator does not yet
support these bits. That's coming in a followup CL.

Change-Id: I362e9227694f9b862eaad100f6afca45a9b62a01
Bug: skia:12248
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436336
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index a954623..9c316be 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -346,7 +346,6 @@
   "/sksl/shared/OutParamsNoInline.sksl",
   "/sksl/shared/OutParamsTricky.sksl",
   "/sksl/shared/Overflow.sksl",
-  "/sksl/shared/PrecisionQualifiers.sksl",
   "/sksl/shared/RectangleTexture.sksl",
   "/sksl/shared/ResizeMatrix.sksl",
   "/sksl/shared/ResizeMatrixNonsquare.sksl",
@@ -524,6 +523,7 @@
   "/sksl/runtime/GlobalVariables.rts",
   "/sksl/runtime/LoopInt.rts",
   "/sksl/runtime/LoopFloat.rts",
+  "/sksl/runtime/PrecisionQualifiers.rts",
   "/sksl/runtime/SampleWithExplicitCoord.rts",
   "/sksl/runtime/VectorIndexing.rts",
 ]
diff --git a/include/private/SkSLModifiers.h b/include/private/SkSLModifiers.h
index a5497b7..aca2484 100644
--- a/include/private/SkSLModifiers.h
+++ b/include/private/SkSLModifiers.h
@@ -27,9 +27,11 @@
         kFlat_Flag           = 1 <<  4,
         kNoPerspective_Flag  = 1 <<  5,
         kHasSideEffects_Flag = 1 <<  6,
-
-        kInline_Flag         = 1 <<  8,
-        kNoInline_Flag       = 1 <<  9,
+        kHighp_Flag          = 1 <<  7,
+        kMediump_Flag        = 1 <<  8,
+        kLowp_Flag           = 1 <<  9,
+        kInline_Flag         = 1 <<  10,
+        kNoInline_Flag       = 1 <<  11,
     };
 
     Modifiers()
@@ -60,6 +62,15 @@
         if (fFlags & kNoInline_Flag) {
             result += "noinline ";
         }
+        if (fFlags & kHighp_Flag) {
+            result += "highp ";
+        }
+        if (fFlags & kMediump_Flag) {
+            result += "mediump ";
+        }
+        if (fFlags & kLowp_Flag) {
+            result += "lowp ";
+        }
         if ((fFlags & kIn_Flag) && (fFlags & kOut_Flag)) {
             result += "inout ";
         } else if (fFlags & kIn_Flag) {
diff --git a/resources/sksl/runtime/PrecisionQualifiers.rts b/resources/sksl/runtime/PrecisionQualifiers.rts
new file mode 100644
index 0000000..cf72148
--- /dev/null
+++ b/resources/sksl/runtime/PrecisionQualifiers.rts
@@ -0,0 +1,9 @@
+uniform half4 colorGreen;
+
+vec4 main(vec2 coords) {
+    highp vec4 zero = vec4(0);
+    mediump vec4 green = colorGreen;
+    lowp vec4 one = vec4(1);
+
+    return green * one + zero;
+}
diff --git a/resources/sksl/shared/PrecisionQualifiers.sksl b/resources/sksl/shared/PrecisionQualifiers.sksl
deleted file mode 100644
index e5b2159..0000000
--- a/resources/sksl/shared/PrecisionQualifiers.sksl
+++ /dev/null
@@ -1,9 +0,0 @@
-uniform half4 colorGreen;
-
-half4 main(float2 coords) {
-    highp vec4 zero = 0;
-    mediump vec4 green = colorGreen;
-    lowp vec4 one = 1;
-
-    return green * one + zero;
-}
diff --git a/src/sksl/SkSLDSLParser.cpp b/src/sksl/SkSLDSLParser.cpp
index 334ba8e..514e9f9 100644
--- a/src/sksl/SkSLDSLParser.cpp
+++ b/src/sksl/SkSLDSLParser.cpp
@@ -33,6 +33,9 @@
         case Token::Kind::TK_HASSIDEEFFECTS: return Modifiers::kHasSideEffects_Flag;
         case Token::Kind::TK_INLINE:         return Modifiers::kInline_Flag;
         case Token::Kind::TK_NOINLINE:       return Modifiers::kNoInline_Flag;
+        case Token::Kind::TK_HIGHP:          return Modifiers::kHighp_Flag;
+        case Token::Kind::TK_MEDIUMP:        return Modifiers::kMediump_Flag;
+        case Token::Kind::TK_LOWP:           return Modifiers::kLowp_Flag;
         default:                             return 0;
     }
 }
@@ -428,7 +431,10 @@
         return this->varDeclarations();
     }
 
-    if (IsType(this->text(nextToken))) {
+    if (nextToken.fKind == Token::Kind::TK_HIGHP ||
+        nextToken.fKind == Token::Kind::TK_MEDIUMP ||
+        nextToken.fKind == Token::Kind::TK_LOWP ||
+        IsType(this->text(nextToken))) {
         // Statements that begin with a typename are most often variable declarations, but
         // occasionally the type is part of a constructor, and these are actually expression-
         // statements in disguise. First, attempt the common case: parse it as a vardecl.
@@ -742,6 +748,9 @@
         case Token::Kind::TK_SEMICOLON:
             this->nextToken();
             return dsl::Block();
+        case Token::Kind::TK_HIGHP:
+        case Token::Kind::TK_MEDIUMP:
+        case Token::Kind::TK_LOWP:
         case Token::Kind::TK_CONST:
         case Token::Kind::TK_IDENTIFIER:
             return this->varDeclarationsOrExpressionStatement();
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index f47555d..8a84c8d 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -743,6 +743,9 @@
     checkModifier(Modifiers::kHasSideEffects_Flag, "sk_has_side_effects");
     checkModifier(Modifiers::kInline_Flag,         "inline");
     checkModifier(Modifiers::kNoInline_Flag,       "noinline");
+    checkModifier(Modifiers::kHighp_Flag,          "highp");
+    checkModifier(Modifiers::kMediump_Flag,        "mediump");
+    checkModifier(Modifiers::kLowp_Flag,           "lowp");
     SkASSERT(flags == 0);
 
     int layoutFlags = modifiers.fLayout.fFlags;
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index 9936d25..395a3bb 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -52,6 +52,9 @@
         case Token::Kind::TK_HASSIDEEFFECTS: return Modifiers::kHasSideEffects_Flag;
         case Token::Kind::TK_INLINE:         return Modifiers::kInline_Flag;
         case Token::Kind::TK_NOINLINE:       return Modifiers::kNoInline_Flag;
+        case Token::Kind::TK_HIGHP:          return Modifiers::kHighp_Flag;
+        case Token::Kind::TK_MEDIUMP:        return Modifiers::kMediump_Flag;
+        case Token::Kind::TK_LOWP:           return Modifiers::kLowp_Flag;
         default:                             return 0;
     }
 }
@@ -387,7 +390,10 @@
         return this->varDeclarations();
     }
 
-    if (this->isType(this->text(nextToken))) {
+    if (nextToken.fKind == Token::Kind::TK_HIGHP ||
+        nextToken.fKind == Token::Kind::TK_MEDIUMP ||
+        nextToken.fKind == Token::Kind::TK_LOWP ||
+        this->isType(this->text(nextToken))) {
         // Statements that begin with a typename are most often variable declarations, but
         // occasionally the type is part of a constructor, and these are actually expression-
         // statements in disguise. First, attempt the common case: parse it as a vardecl.
@@ -849,6 +855,9 @@
         case Token::Kind::TK_SEMICOLON:
             this->nextToken();
             return this->createNode(start.fOffset, ASTNode::Kind::kBlock);
+        case Token::Kind::TK_HIGHP:
+        case Token::Kind::TK_MEDIUMP:
+        case Token::Kind::TK_LOWP:
         case Token::Kind::TK_CONST:
         case Token::Kind::TK_IDENTIFIER:
             return this->varDeclarationsOrExpressionStatement();
diff --git a/tests/sksl/runtime/PrecisionQualifiers.skvm b/tests/sksl/runtime/PrecisionQualifiers.skvm
new file mode 100644
index 0000000..9afee19
--- /dev/null
+++ b/tests/sksl/runtime/PrecisionQualifiers.skvm
@@ -0,0 +1,6 @@
+### Compilation failed:
+
+error: 4: 'highp' is not permitted here
+error: 5: 'mediump' is not permitted here
+error: 6: 'lowp' is not permitted here
+3 errors
diff --git a/tests/sksl/runtime/PrecisionQualifiers.stage b/tests/sksl/runtime/PrecisionQualifiers.stage
new file mode 100644
index 0000000..9afee19
--- /dev/null
+++ b/tests/sksl/runtime/PrecisionQualifiers.stage
@@ -0,0 +1,6 @@
+### Compilation failed:
+
+error: 4: 'highp' is not permitted here
+error: 5: 'mediump' is not permitted here
+error: 6: 'lowp' is not permitted here
+3 errors
diff --git a/tests/sksl/shared/PrecisionQualifiers.asm.frag b/tests/sksl/shared/PrecisionQualifiers.asm.frag
deleted file mode 100644
index 9c93813..0000000
--- a/tests/sksl/shared/PrecisionQualifiers.asm.frag
+++ /dev/null
@@ -1,4 +0,0 @@
-### Compilation failed:
-
-error: 4: expected expression, but found 'highp'
-1 error
diff --git a/tests/sksl/shared/PrecisionQualifiers.glsl b/tests/sksl/shared/PrecisionQualifiers.glsl
deleted file mode 100644
index 9c93813..0000000
--- a/tests/sksl/shared/PrecisionQualifiers.glsl
+++ /dev/null
@@ -1,4 +0,0 @@
-### Compilation failed:
-
-error: 4: expected expression, but found 'highp'
-1 error
diff --git a/tests/sksl/shared/PrecisionQualifiers.metal b/tests/sksl/shared/PrecisionQualifiers.metal
deleted file mode 100644
index 9c93813..0000000
--- a/tests/sksl/shared/PrecisionQualifiers.metal
+++ /dev/null
@@ -1,4 +0,0 @@
-### Compilation failed:
-
-error: 4: expected expression, but found 'highp'
-1 error